while 循环只读取文件的第一行
while-loop read only first line from file
欢迎,我的 while 循环有问题。它只读取 file.txt 的第一行。在添加按 strtok_r 拆分我的行的功能之前,我的应用程序不起作用 good.The 此 while 循环的目的是从文件中读取所有行并按“|”拆分每一行这些部分添加到适当的选项卡。
我应该怎么办?
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mem.h>
#include <assert.h>
struct movie {
char title[100];
int year;
char genre[100];
};
int i = 0;
struct movie *movies[50];
int porownaj(struct movie* first, struct movie* second)
{
if(first->year==second->year){
if(first->title>second->title){
return 1;
}
if(first->title<second->title){
return -1;
}
if(first->title==second->title){
if(first->genre>second->genre){
return 1;
}
if(first->genre<second->genre){
return -1;
}
if(first->genre==second->genre){
return 0;
}
}
}
if(first->year>second->year){
return 1;
}
if(first->year<second->year){
return -1;
}
if(first->title==second->title){
if(first->year>second->year){
return 1;
}
if(first->year<second->year){
return -1;
}
if(first->year==second->year){
if(first->genre>second->genre){
return 1;
}
if(first->genre<second->genre){
return -1;
}
if(first->genre==second->genre){
return 0;
}
}
}
if(first->title>second->title){
return 1;
}
if(first->title<second->title){
return -1;
}
if(first->genre==second->genre){
if(first->year>second->year){
return 1;
}
if(first->year<second->year){
return -1;
}
if(first->year==second->year){
if(first->title>second->title){
return 1;
}
if(first->title<second->title){
return -1;
}
if(first->title==second->title){
return 0;
}
}
}
if(first->genre>second->genre){
return 1;
}
if(first->genre<second->genre){
return -1;
}
}
void zamien(struct movie* movies[50], int x, int y)
{
struct movie* tmpMovie = movies[x];
movies[x] = movies[y];
movies[y] = tmpMovie;
}
int main()
{
struct movie *movies[50];
do
{
printf("\n");
printf("Projekt nr 6 \n");
printf("\n");
printf("\b MENU GLOWNE \n");
printf("|-----------------| \n");
printf("[1]Baza filmow \n");
printf("[2]Dodaj film \n");
printf("[3]Zakoncz Program \n");
printf("|-----------------| \n");
char znak;
printf("Wybierz opcje z menu: ");
scanf("%s", &znak);
system("cls");
switch (znak)
{
case '1':
system("cls");
printf("Wybrales opcje BAZA FILMOW \n");
printf("TYTUL | ROK | GATUNEK\n");
printf("----------------------\n");
FILE *baza;
if ((baza = fopen("movies.txt", "r")) == NULL)
{
system("cls");
printf("Blad otwarcia pliku\n");
exit(1);
}
char tekst[512];
char *title = NULL;
char *year = NULL;
char *genre = NULL;
char *buffer = NULL;
int x = 0;
while (fgets(tekst, 512, baza) != NULL)
{
printf("%s", tekst);
title = strtok_r(tekst, "|", &buffer);
assert(title != NULL);
strcpy(movies[x]->title, title);
year = strtok_r(NULL, "|", &buffer);
assert(year != NULL);
movies[x]->year = atoi(year);
genre = strtok_r(NULL, "|", &buffer);
assert(genre != NULL);
strcpy(movies[x]->genre, genre);
x++;
}fclose(baza);
do
{
printf("\n[1]Sortuj wg. tytulu");
printf("\n[2]Sortuj wg. roku produkcji");
printf("\n[3]Sortuj wg. gatunku filmu");
printf("\n[4]Wroc do glownego menu\n");
printf("|-----------------|\n");
char click;
printf("\nWybierz opcje: ");
scanf("%s", &click);
switch (click)
{
case '1':
system("cls");
printf("Sorotowanie wg. tytulu");
/*
for(int i=0;i<10-1;i++){
for(int j=0;j<10-i-1;j++){
if(porownaj(&title[j],&title[j+1])>0){
zamien(&title[j],&title[j+1]);
}
}
}
for(int i=0;i<10;i++){
printf("(%d, %d)", title[i].x, );
}
*/
break;
case '2':
system("cls");
printf("Sorotowanie wg. roku produkcji");
/*
for(int i=0;i<10-1;i++){
for(int j=0;j<10-i-1;j++){
if(porownaj(&year[j],&year[j+1])>0){
zamien(&year[j],&year[j+1]);
}
}
}
for(int i=0;i<10;i++){
printf("(%d, %d)", year[i].x, );
}
*/
break;
case '3':
system("cls");
printf("Sorotowanie wg. gatunku filmu");
break;
case '4':
system("cls");
return main();
default:
system("cls");
printf("Nie ma takiej opcji. Program sie wylaczy!");
return 0;
}
} while (1);
case '2':
system("cls");
printf("Wybrales opcje DODAJ FILM \n");
movies[i] = malloc(sizeof(movie));
printf("Podaj nazwe filmu: ");
while ((getchar()) != '\n');
gets(movies[i]->title);
printf("Podaj rok produkcji: ");
scanf("%d", &(movies[i]->year));
printf("Podaj gatunek filmu: ");
while ((getchar()) != '\n');
gets(movies[i]->genre);
fflush(stdin);
FILE *plik = fopen("movies.txt", "a+");
fprintf(plik, "%s | %d | %s \n", movies[i]->title, movies[i]->year, movies[i]->genre);
fclose(plik);
i++;
printf("Zapisane..");
continue;
case '3':
system("cls");
printf("ZAKONCZ PROGRAM \n");
return 0;
default:
printf("Nie ma takiej opcji! \n");
return main();
}
}while (1);
return (0);
}
movies.txt:
Title | 1234 | Scifi
Title_2 | 4321 | SciFI
除了任何其他可能的问题之外,这些行是有问题的:
title=movies[x]->title;
year=movies[x]->year;
genre=movies[x]->genre;
- 正如评论中所说,分配必须颠倒(
movies[x]->foo = foo;
)
- 你需要复制字符串,否则你保存了 tekst 的子地址,每个循环都会修改它,当你使用它们时可能会消失
所以
movies[x]->title = strdup(title);
movies[x]->year = year;
movies[x]->genre = strdup(genre);
或者当然,如果 movies[x]->title
和 movies[x]->genre
是 char[]
而不是 char*
,则代码必须复制而不是复制:
strcpy(movies[x]->title, title);
movies[x]->year = year;
strcpy(movies[x]->genre, genre);
如果需要,将 strcpy 替换为 strncpy 以防止溢出
我打赌每一行都印有printf("%s", tekst);
。
但是您忘记了 strtok
而不是 复制字符串。因此(如果您以相反的方式固定您的分配),您仍然将 poinetrs 分配到相同的 tekst
变量到所有电影。而是分配内存并复制字符串:
title = strtok_r(tekst, "|", &buffer);
movies[x]->title= malloc(strlen(title)+1);
strcpy(movies[x]->title, title);
其他字符串变量也一样。
你的程序中有很多错误。
从这里开始:
char title = NULL;
char year = NULL;
char genre = NULL;
与此一起:
title = strtok_r(tekst, "|", &buffer);
year = strtok_r(NULL, "|", &buffer);
genre = strtok_r(NULL, "|", &buffer);
int year = atoi(year);
您将 title
定义为 char
,但 strtok_r
returns 为 char*
。因此,您可以通过将 "char pointer" 存储在 "char" 变量中来覆盖内存。
这可能会破坏文件指针。您得到的错误 0xC0000005(正如您在评论中提到的)可能表明:
Application Error 0xc0000005 (Access Violation) error is usually caused by your computer not being able to correctly process the files...
将定义更改为:
char *title = NULL;
char *year = NULL;
char *genre = NULL;
进一步:
year = strtok_r(NULL, "|", &buffer); // A variable named year
genre = strtok_r(NULL, "|", &buffer);
int year = atoi(year); // A NEW variable with same name!!
改为:
year = strtok_r(NULL, "|", &buffer);
genre = strtok_r(NULL, "|", &buffer);
int yearN = atoi(year); // Use another name
此外,在调用 atoi
之前,您应该始终检查 year
是否为 not NULL
所以我的建议是简化您的调试代码。尝试:
FILE *baza;
if ((baza = fopen("movies.txt", "r")) == NULL)
{
system("cls");
printf("Blad otwarcia pliku\n");
exit(1);
}
char tekst[512];
char* title = NULL;
char* year = NULL;
char* genre = NULL;
char* buffer = NULL;
int x = 0;
printf("while-loop start\n");
while (fgets(tekst, 512, baza) != NULL)
{
printf("%s", tekst);
//x++;
//title = strtok_r(tekst, "|", &buffer);
//year = strtok_r(NULL, "|", &buffer);
//genre = strtok_r(NULL, "|", &buffer);
//int year = atoi(year);
//title=movies[x]->title;
//year=movies[x]->year;
//genre=movies[x]->genre;
}
printf("while-loop complete\n");
现在检查您从此代码获得的输出。如果按预期工作,您可以开始逐行取消注释。
最后我猜你的函数应该是这样的:
FILE *baza;
if ((baza = fopen("movies.txt", "r")) == NULL)
{
system("cls");
printf("Blad otwarcia pliku\n");
exit(1);
}
char tekst[512];
char* title = NULL;
char* year = NULL;
char* genre = NULL;
char* buffer = NULL;
int x = 0;
while (fgets(tekst, 512, baza) != NULL)
{
printf("%s", tekst);
title = strtok_r(tekst, "|", &buffer);
assert(title != NULL);
strcpy(movies[x]->title, title);
year = strtok_r(NULL, "|", &buffer);
assert(year != NULL);
movies[x]->year = atoi(year);
genre = strtok_r(NULL, "|", &buffer);
assert(genre != NULL);
strcpy(movies[x]->genre, genre);
x++;
}
上面假设你已经为movies
中的所有指针分配了内存。喜欢:
struct movie { char title[100]; int year; char genre[100]; };
int main() {
int i = 0;
struct movie *movies[50];
for(i=0; i<50; ++i) movies[i] = malloc(sizeof *movies);
. . .
欢迎,我的 while 循环有问题。它只读取 file.txt 的第一行。在添加按 strtok_r 拆分我的行的功能之前,我的应用程序不起作用 good.The 此 while 循环的目的是从文件中读取所有行并按“|”拆分每一行这些部分添加到适当的选项卡。 我应该怎么办? 这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mem.h>
#include <assert.h>
struct movie {
char title[100];
int year;
char genre[100];
};
int i = 0;
struct movie *movies[50];
int porownaj(struct movie* first, struct movie* second)
{
if(first->year==second->year){
if(first->title>second->title){
return 1;
}
if(first->title<second->title){
return -1;
}
if(first->title==second->title){
if(first->genre>second->genre){
return 1;
}
if(first->genre<second->genre){
return -1;
}
if(first->genre==second->genre){
return 0;
}
}
}
if(first->year>second->year){
return 1;
}
if(first->year<second->year){
return -1;
}
if(first->title==second->title){
if(first->year>second->year){
return 1;
}
if(first->year<second->year){
return -1;
}
if(first->year==second->year){
if(first->genre>second->genre){
return 1;
}
if(first->genre<second->genre){
return -1;
}
if(first->genre==second->genre){
return 0;
}
}
}
if(first->title>second->title){
return 1;
}
if(first->title<second->title){
return -1;
}
if(first->genre==second->genre){
if(first->year>second->year){
return 1;
}
if(first->year<second->year){
return -1;
}
if(first->year==second->year){
if(first->title>second->title){
return 1;
}
if(first->title<second->title){
return -1;
}
if(first->title==second->title){
return 0;
}
}
}
if(first->genre>second->genre){
return 1;
}
if(first->genre<second->genre){
return -1;
}
}
void zamien(struct movie* movies[50], int x, int y)
{
struct movie* tmpMovie = movies[x];
movies[x] = movies[y];
movies[y] = tmpMovie;
}
int main()
{
struct movie *movies[50];
do
{
printf("\n");
printf("Projekt nr 6 \n");
printf("\n");
printf("\b MENU GLOWNE \n");
printf("|-----------------| \n");
printf("[1]Baza filmow \n");
printf("[2]Dodaj film \n");
printf("[3]Zakoncz Program \n");
printf("|-----------------| \n");
char znak;
printf("Wybierz opcje z menu: ");
scanf("%s", &znak);
system("cls");
switch (znak)
{
case '1':
system("cls");
printf("Wybrales opcje BAZA FILMOW \n");
printf("TYTUL | ROK | GATUNEK\n");
printf("----------------------\n");
FILE *baza;
if ((baza = fopen("movies.txt", "r")) == NULL)
{
system("cls");
printf("Blad otwarcia pliku\n");
exit(1);
}
char tekst[512];
char *title = NULL;
char *year = NULL;
char *genre = NULL;
char *buffer = NULL;
int x = 0;
while (fgets(tekst, 512, baza) != NULL)
{
printf("%s", tekst);
title = strtok_r(tekst, "|", &buffer);
assert(title != NULL);
strcpy(movies[x]->title, title);
year = strtok_r(NULL, "|", &buffer);
assert(year != NULL);
movies[x]->year = atoi(year);
genre = strtok_r(NULL, "|", &buffer);
assert(genre != NULL);
strcpy(movies[x]->genre, genre);
x++;
}fclose(baza);
do
{
printf("\n[1]Sortuj wg. tytulu");
printf("\n[2]Sortuj wg. roku produkcji");
printf("\n[3]Sortuj wg. gatunku filmu");
printf("\n[4]Wroc do glownego menu\n");
printf("|-----------------|\n");
char click;
printf("\nWybierz opcje: ");
scanf("%s", &click);
switch (click)
{
case '1':
system("cls");
printf("Sorotowanie wg. tytulu");
/*
for(int i=0;i<10-1;i++){
for(int j=0;j<10-i-1;j++){
if(porownaj(&title[j],&title[j+1])>0){
zamien(&title[j],&title[j+1]);
}
}
}
for(int i=0;i<10;i++){
printf("(%d, %d)", title[i].x, );
}
*/
break;
case '2':
system("cls");
printf("Sorotowanie wg. roku produkcji");
/*
for(int i=0;i<10-1;i++){
for(int j=0;j<10-i-1;j++){
if(porownaj(&year[j],&year[j+1])>0){
zamien(&year[j],&year[j+1]);
}
}
}
for(int i=0;i<10;i++){
printf("(%d, %d)", year[i].x, );
}
*/
break;
case '3':
system("cls");
printf("Sorotowanie wg. gatunku filmu");
break;
case '4':
system("cls");
return main();
default:
system("cls");
printf("Nie ma takiej opcji. Program sie wylaczy!");
return 0;
}
} while (1);
case '2':
system("cls");
printf("Wybrales opcje DODAJ FILM \n");
movies[i] = malloc(sizeof(movie));
printf("Podaj nazwe filmu: ");
while ((getchar()) != '\n');
gets(movies[i]->title);
printf("Podaj rok produkcji: ");
scanf("%d", &(movies[i]->year));
printf("Podaj gatunek filmu: ");
while ((getchar()) != '\n');
gets(movies[i]->genre);
fflush(stdin);
FILE *plik = fopen("movies.txt", "a+");
fprintf(plik, "%s | %d | %s \n", movies[i]->title, movies[i]->year, movies[i]->genre);
fclose(plik);
i++;
printf("Zapisane..");
continue;
case '3':
system("cls");
printf("ZAKONCZ PROGRAM \n");
return 0;
default:
printf("Nie ma takiej opcji! \n");
return main();
}
}while (1);
return (0);
}
movies.txt:
Title | 1234 | Scifi
Title_2 | 4321 | SciFI
除了任何其他可能的问题之外,这些行是有问题的:
title=movies[x]->title;
year=movies[x]->year;
genre=movies[x]->genre;
- 正如评论中所说,分配必须颠倒(
movies[x]->foo = foo;
) - 你需要复制字符串,否则你保存了 tekst 的子地址,每个循环都会修改它,当你使用它们时可能会消失
所以
movies[x]->title = strdup(title);
movies[x]->year = year;
movies[x]->genre = strdup(genre);
或者当然,如果 movies[x]->title
和 movies[x]->genre
是 char[]
而不是 char*
,则代码必须复制而不是复制:
strcpy(movies[x]->title, title);
movies[x]->year = year;
strcpy(movies[x]->genre, genre);
如果需要,将 strcpy 替换为 strncpy 以防止溢出
我打赌每一行都印有printf("%s", tekst);
。
但是您忘记了 strtok
而不是 复制字符串。因此(如果您以相反的方式固定您的分配),您仍然将 poinetrs 分配到相同的 tekst
变量到所有电影。而是分配内存并复制字符串:
title = strtok_r(tekst, "|", &buffer);
movies[x]->title= malloc(strlen(title)+1);
strcpy(movies[x]->title, title);
其他字符串变量也一样。
你的程序中有很多错误。
从这里开始:
char title = NULL;
char year = NULL;
char genre = NULL;
与此一起:
title = strtok_r(tekst, "|", &buffer);
year = strtok_r(NULL, "|", &buffer);
genre = strtok_r(NULL, "|", &buffer);
int year = atoi(year);
您将 title
定义为 char
,但 strtok_r
returns 为 char*
。因此,您可以通过将 "char pointer" 存储在 "char" 变量中来覆盖内存。
这可能会破坏文件指针。您得到的错误 0xC0000005(正如您在评论中提到的)可能表明:
Application Error 0xc0000005 (Access Violation) error is usually caused by your computer not being able to correctly process the files...
将定义更改为:
char *title = NULL;
char *year = NULL;
char *genre = NULL;
进一步:
year = strtok_r(NULL, "|", &buffer); // A variable named year
genre = strtok_r(NULL, "|", &buffer);
int year = atoi(year); // A NEW variable with same name!!
改为:
year = strtok_r(NULL, "|", &buffer);
genre = strtok_r(NULL, "|", &buffer);
int yearN = atoi(year); // Use another name
此外,在调用 atoi
year
是否为 not NULL
所以我的建议是简化您的调试代码。尝试:
FILE *baza;
if ((baza = fopen("movies.txt", "r")) == NULL)
{
system("cls");
printf("Blad otwarcia pliku\n");
exit(1);
}
char tekst[512];
char* title = NULL;
char* year = NULL;
char* genre = NULL;
char* buffer = NULL;
int x = 0;
printf("while-loop start\n");
while (fgets(tekst, 512, baza) != NULL)
{
printf("%s", tekst);
//x++;
//title = strtok_r(tekst, "|", &buffer);
//year = strtok_r(NULL, "|", &buffer);
//genre = strtok_r(NULL, "|", &buffer);
//int year = atoi(year);
//title=movies[x]->title;
//year=movies[x]->year;
//genre=movies[x]->genre;
}
printf("while-loop complete\n");
现在检查您从此代码获得的输出。如果按预期工作,您可以开始逐行取消注释。
最后我猜你的函数应该是这样的:
FILE *baza;
if ((baza = fopen("movies.txt", "r")) == NULL)
{
system("cls");
printf("Blad otwarcia pliku\n");
exit(1);
}
char tekst[512];
char* title = NULL;
char* year = NULL;
char* genre = NULL;
char* buffer = NULL;
int x = 0;
while (fgets(tekst, 512, baza) != NULL)
{
printf("%s", tekst);
title = strtok_r(tekst, "|", &buffer);
assert(title != NULL);
strcpy(movies[x]->title, title);
year = strtok_r(NULL, "|", &buffer);
assert(year != NULL);
movies[x]->year = atoi(year);
genre = strtok_r(NULL, "|", &buffer);
assert(genre != NULL);
strcpy(movies[x]->genre, genre);
x++;
}
上面假设你已经为movies
中的所有指针分配了内存。喜欢:
struct movie { char title[100]; int year; char genre[100]; };
int main() {
int i = 0;
struct movie *movies[50];
for(i=0; i<50; ++i) movies[i] = malloc(sizeof *movies);
. . .