C解决了fscanf的问题

C解决了fscanf的问题,c,C,感谢所有的答案,修正后的代码没有一个愚蠢的错误工作。。。我用相同的文件指针“数据库”打开了两个文件 我读过很多这样的问题,但我无法摆脱,我快疯了。 我必须做的练习要求我在一个file.txt文件中组织列表中的项目,该文件包含以下类型的元素:Name姓氏Age Wage,按姓氏的字母顺序排列。 我已经创建了一个函数来将元素插入到文件中,它运行良好。 然后我转到函数来组织它们,但过程在fscanf之后停止,并放置一些测试printf,我看到没有为字符串分配值或分配了荒谬的数字。 请帮忙。。。谢谢 代

感谢所有的答案,修正后的代码没有一个愚蠢的错误工作。。。我用相同的文件指针“数据库”打开了两个文件

我读过很多这样的问题,但我无法摆脱,我快疯了。 我必须做的练习要求我在一个file.txt文件中组织列表中的项目,该文件包含以下类型的元素:Name姓氏Age Wage,按姓氏的字母顺序排列。 我已经创建了一个函数来将元素插入到文件中,它运行良好。 然后我转到函数来组织它们,但过程在fscanf之后停止,并放置一些测试printf,我看到没有为字符串分配值或分配了荒谬的数字。 请帮忙。。。谢谢

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX 64
#define MAXFILE 100

void insert();
int fullcheck();
void sort();

typedef struct {
    char name[MAX];
    char surname[MAX];
    int age;
    double wage;
} data;

int main() {
    insert();
    return EXIT_SUCCESS;
}

void insert() {
    char c;
    int i;
    data tmp;
    FILE* database;
    if ((fullcheck())>MAXFILE-1)
        printf("Errore: database pieno.\n");
    else {
        database=fopen("database.txt", "a");
        printf("Nome: ");
        fgets(tmp.name, MAX, stdin);
        tmp.name[strlen(tmp.name)-1]='\0';
        printf("Cognome: ");
        fgets(tmp.surname, MAX, stdin);
        tmp.surname[strlen(tmp.surname)-1]='\0';
        for (i=0; i<strlen(tmp.surname); i++) {
            if (tmp.surname[i]==' ')
                tmp.surname[i]='#';
        }
        printf("Eta': ");
        scanf("%d", &tmp.age);
        printf("Salario: ");
        scanf("%lf", &tmp.wage);
        while((c=getchar())!='\n');
        fprintf(database, "%s %s %d %.0lf \n", tmp.name, tmp.surname, tmp.age, tmp.wage);
        fflush(database); fclose(database);
        if ((fullcheck())>1)
            sort();
    }
}

int fullcheck() {
    char c;
    int r=0;
    FILE* database;
    if ((database=fopen("database.txt", "r"))==NULL) {
        return 0;
    }
    else {
        while((c=getc(database))!=EOF) {
            if(c=='\n')
                r++;
        }
        return r;
    }
}

void sort() {
    char tmpstr[MAX];
    int len=fullcheck(), i, a, b;
    data tmp[len];
    FILE* database;
    FILE* sorted;
    database=fopen("database.txt", "r");
    database=fopen("sorted.txt", "w");
    for (i=0; i<=len; i++) {
        fscanf(database, "%s %s %d %lf \n", &tmp[i].name, &tmp[i].surname, &tmp[i].age, &tmp[i].wage);
    }
    for (a=0 ; a<(len-1); a++) {
        for (b=0; b<(len-1); b++) {
            if ((tolower(tmp[b].surname[0]))>(tolower(tmp[b+1].surname[0]))) {
                strcpy(tmpstr, tmp[b].surname);
                strcpy(tmp[b].surname, tmp[b+1].surname);
                strcpy(tmp[b+1].surname, tmpstr);
            }
        }
    }
    for (a=0; a<(len-1); a++) {
        fprintf(sorted, "%s %s %d %.0lf \n", tmp[a].name, tmp[a].surname, tmp[a].age, tmp[a].wage);
    }
    fflush(database); fclose(database); remove("database.txt");
    fflush(sorted); fclose(sorted); rename("sorted.txt", "database.txt");
} 
#包括
#包括
#包括
#包括
#定义最大64
#定义MAXFILE 100
无效插入();
int fullcheck();
无效排序();
类型定义结构{
字符名[MAX];
char姓氏[MAX];
智力年龄;
双倍工资;
}数据;
int main(){
插入();
返回退出成功;
}
空白插入(){
字符c;
int i;
数据tmp;
文件*数据库;
如果((fullcheck())>MAXFILE-1)
printf(“error:database pieno.\n”);
否则{
database=fopen(“database.txt”,“a”);
printf(“Nome:”);
fgets(tmp.name、最大值、标准输入);
tmp.name[strlen(tmp.name)-1]='\0';
printf(“Cognome:”);
fgets(tmp.姓氏、MAX、stdin);
tmp.姓氏[strlen(tmp.姓氏)-1]='\0';
对于(i=0;i1)
排序();
}
}
int fullcheck(){
字符c;
int r=0;
文件*数据库;
if((database=fopen(“database.txt”,“r”))==NULL){
返回0;
}
否则{
而((c=getc(数据库))!=EOF){
如果(c=='\n')
r++;
}
返回r;
}
}
空排序(){
字符tmpstr[MAX];
int len=fullcheck(),i,a,b;
数据tmp[len];
文件*数据库;
文件*已排序;
database=fopen(“database.txt”、“r”);
数据库=fopen(“sorted.txt”,“w”);

对于(i=0;i关闭1

代码试图读入tmp[]len+1元素

data tmp[len];
for (i=0; i<=len; i++) {  // too many
    fscanf(database, "%s %s %d %lf \n", &tmp[i].name, &tmp[i].surname, &tmp[i].age, &tmp[i].wage);
}
更好的代码是将带有
fgets()
的行读入stirng,然后尝试解析字符串

关闭2次

如果最后一行没有以'\n'结尾,则代码查找行数的尝试可能会缩短1

另类

size_t fullcheck(void) {
    FILE* database = fopen("database.txt", "r");
    if (database == NULL) {
        return 0;
    }
    int previous = '\n';
    int c;
    size_t r=0;
    while((c=getc(database))!=EOF) {
      if (previous == '\n') r++;
      previous = c;
    }
    fclose(database);
    return r;
}
缺少
fclose()

int

使用
int
来区分
fgetc()
的典型257个不同返回值。注意,当char`未单选时,OP的代码是一个无限循环

更多的不幸

打印已排序列表的循环以1为单位关闭,太短。排序本身只查看每个名称的第一个字母,应使用
strcmp


可能更多?

在每次返回之前,请确保关闭此处的文件:

int fullcheck() {
    char c;
    int r=0;
    FILE* database;
    if ((database=fopen("database.txt", "r"))==NULL) {
        fclose(database);
        return 0;
    }
    else {
        while((c=getc(database))!=EOF) {
            if(c=='\n')
                r++;
        }
        fclose(database);
        return r;
    }
}
这里还有一点循环计数器的修正:

void sort() {
    char tmpstr[MAX];
    int len=fullcheck(), i, a, b;
    data tmp[len];
    FILE* database;
    FILE* sorted;
    database=fopen("database.txt", "r");
    sorted=fopen("sorted.txt", "w+");
    for (i=0; i<len; i++) {
        fscanf(database, "%s %s %d %lf \n", &tmp[i].name, &tmp[i].surname, &tmp[i].age, &tmp[i].wage);
        printf("%s", tmp[b+1].surname);
                system("pause");
    }
    for (a=0 ; a<(len); a++) {
        for (b=0; b<(len); b++) {
            if ((tolower(tmp[b].surname[0]))>(tolower(tmp[b+1].surname[0]))) {
                strcpy(tmpstr, tmp[b].surname);
                strcpy(tmp[b].surname, tmp[b+1].surname);
                strcpy(tmp[b+1].surname, tmpstr);
                printf("%s", tmp[b+1].surname);
                system("pause");
            }
        }
    }
    for (a=0; a<(len); a++) {
        fprintf(sorted, "%s %s %d %.0lf \n", tmp[a].name, tmp[a].surname, tmp[a].age, tmp[a].wage);
    }
    fclose(sorted); 
    fclose(database); 
} 
void排序(){
字符tmpstr[MAX];
int len=fullcheck(),i,a,b;
数据tmp[len];
文件*数据库;
文件*已排序;
database=fopen(“database.txt”、“r”);
sorted=fopen(“sorted.txt”,“w+”);

对于(i=0;模仿
fgets
scanf
只是自找麻烦。通过使用
fgets
读取每一行来修复它,然后使用
sscanf
strtol
转换一行上的数字。
fullcheck()
打开文件后不会关闭它。另外,在
fullcheck
中,
c
应该是
int
。发布一些
database.txt
@user3386109的示例行,说明混合
fgets()
和scanf()是正确的`通常情况下是不好的,但是OP在这里的代码不会因此而失败。@chux:是的,你是正确的。这里有更多的答案。打印排序列表的循环被关闭了一个,太短了。排序本身只查看每个名称的第一个字母,应该使用
strcmp
void sort() {
    char tmpstr[MAX];
    int len=fullcheck(), i, a, b;
    data tmp[len];
    FILE* database;
    FILE* sorted;
    database=fopen("database.txt", "r");
    sorted=fopen("sorted.txt", "w+");
    for (i=0; i<len; i++) {
        fscanf(database, "%s %s %d %lf \n", &tmp[i].name, &tmp[i].surname, &tmp[i].age, &tmp[i].wage);
        printf("%s", tmp[b+1].surname);
                system("pause");
    }
    for (a=0 ; a<(len); a++) {
        for (b=0; b<(len); b++) {
            if ((tolower(tmp[b].surname[0]))>(tolower(tmp[b+1].surname[0]))) {
                strcpy(tmpstr, tmp[b].surname);
                strcpy(tmp[b].surname, tmp[b+1].surname);
                strcpy(tmp[b+1].surname, tmpstr);
                printf("%s", tmp[b+1].surname);
                system("pause");
            }
        }
    }
    for (a=0; a<(len); a++) {
        fprintf(sorted, "%s %s %d %.0lf \n", tmp[a].name, tmp[a].surname, tmp[a].age, tmp[a].wage);
    }
    fclose(sorted); 
    fclose(database); 
}