在调用fscanf时,数组更改第一个值而不显式修改它

时间:2011-09-15 19:46:30

标签: c arrays file-io char scanf

我正从std中读取一个值并将其存储在数组min[3]中,然后继续进行数组比较。因此在比较之前永远不会触及min

调试后,我注意到min[0]在执行此行时从输入值更改为\0

fscanf(locDayFile, "%s", extractedHour);

其中locDayFileextractedHour被声明为:

FILE* locDayFile;
char extractedHour[3];

关于出了什么问题的任何想法?

编辑我在这里发布代码:

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <math.h>

struct coords{
    float coord[3];
    char station[5];
    struct coords *next;
};

void Add(struct coords**,char*, float*);
float* Get(struct coords*, char*);

int main(){

    DIR *rootFolder, *subFolder;
    struct dirent *rootEnt, *subEnt;
    char rootFolderName[260], subFolderName[260];

    FILE *locDayFile,  *headers, *coordFile;
    FILE *stationDay, *yearDay, *time, *reference;
    char locDayFileName[260], headersFileName[260], coordFileName[260];
    char stationDayName[260], yearDayName[260], timeName[260], referenceName[260];
    char result[260];
    char make[260];

    char readLine[256];

    char searchingFolderName[9], folderCmp[9];

    char location[7], year[5], day[4], hour[3], min[3], referenceStation[5];
    char locationTest[7], dayTest[4];
    char extractedStation[5], extractedYear[5], extratedDay[4], extractedHour[3], extractedMin[3];
    char rms[7];
    float delay, refereDelay = 0;
    float *coordinates;

    char choice;

    printf("Please enter the following information:\n");
    printf("Location: ");
    scanf("%s", location);
    memmove(location+1, location, 4);
    location[0] = 'o';
    location[5] = 'a';
    location[6] = '\0';
    printf("Year: ");
    scanf("%s", year);
    printf("Day: ");
    scanf("%s", day);

    sprintf(searchingFolderName, "%s_%s", year, day);

    hour[0] = '\0';
    min[0] = '\0';
    referenceStation[0] = '\0';
    referenceName[0] = '\0';
    printf("Do you wish to enter the time?(Y/N): ");
    do{
        scanf("%c", &choice);
    }while(choice != 'Y' && choice != 'y' && choice != 'N' && choice != 'n');
    if(choice == 'Y' || choice == 'y'){
        printf("Hour: ");
        scanf("%s", hour);
        printf("Minutes: ");
        scanf("%s", min);
    }
    printf("Do you wish to enter a reference station?(Y/N): ");
    do{
        scanf("%c", &choice);
    }while(choice != 'Y' && choice != 'y' && choice != 'N' && choice != 'n');
    if(choice == 'Y' || choice == 'y'){
        printf("Reference station: ");
        scanf("%s", referenceStation);
    }

    printf("Root folder path: ");
    scanf("%s", rootFolderName);

    struct coords *c;
    c = NULL;

    printf("Coordinates file path: ");
    scanf("%s", coordFileName);
    coordFile = fopen(coordFileName, "r");
    if(coordFile != NULL){
        char st[5];
        float coords[3];
        while(!feof(coordFile)){
            fscanf(coordFile, "%s", st);
            fscanf(coordFile, "%f", &coords[0]);
            fscanf(coordFile, "%f", &coords[1]);
            fscanf(coordFile, "%f", &coords[2]);

            Add(&c, st, coords);
        }
    }

    if((rootFolder = opendir(rootFolderName)) != NULL){
        while((rootEnt = readdir(rootFolder)) != NULL){

            sprintf(result, "%sresults/", rootFolderName);
            sprintf(make, "mkdir -p %s", result);
            system(make);

            folderCmp[0] = '\0';
            strncpy(folderCmp, rootEnt->d_name, 8);
            folderCmp[8] = '\0';

            if(strcmp(folderCmp, searchingFolderName) == 0){

                sprintf(subFolderName, "%s%s/", rootFolderName, rootEnt->d_name);

                if((subFolder = opendir(subFolderName)) != NULL){
                    while((subEnt = readdir(subFolder)) != NULL){

                        strncpy(locationTest, subEnt->d_name, 6);
                        locationTest[6] = '\0';
                        strncpy(dayTest, (subEnt->d_name)+7, 3);
                        dayTest[3] = '\0';
                        if((strcmp(location, locationTest) == 0) && (strcmp(day, dayTest) == 0)){

                            sprintf(locDayFileName, "%s%s", subFolderName, subEnt->d_name);
                            locDayFile = fopen(locDayFileName, "r");

                            while(!feof(locDayFile)){

                                char garbage[25];

                                fscanf(locDayFile, "%s", garbage);
                                if(strcmp(garbage, "ATM_ZEN") == 0){

                                    sprintf(headersFileName, "%sheaders_%s-%s", rootFolderName, year, day);
                                    headers = fopen(headersFileName, "a+");

                                    fscanf(locDayFile, "%s", garbage);

                                    fscanf(locDayFile, "%s", extractedStation);//3rd column.
                                    fprintf(headers, "%s\t", extractedStation);

                                    fscanf(locDayFile, "%s", garbage);

                                    fscanf(locDayFile, "%s", extractedYear);//5th column.
                                    fprintf(headers, "%s\t", extractedYear);

                                    fscanf(locDayFile, "%s", garbage);

                                    fscanf(locDayFile, "%s", extratedDay);//7th column.
                                    fprintf(headers, "%s\t", extratedDay);

                                    fscanf(locDayFile, "%s", extractedHour);//8th column.
                                    fprintf(headers, "%s\t", extractedHour);

                                    fscanf(locDayFile, "%s", extractedMin);//9th column.
                                    fprintf(headers, "%s\t", extractedMin);

                                    fscanf(locDayFile, "%s", garbage);
                                    fscanf(locDayFile, "%s", garbage);

                                    fscanf(locDayFile, "%f", &delay);//12th column.
                                    fscanf(locDayFile, "%s", rms);//13 column.
                                    fprintf(headers, "%s\t", rms);
                                    fprintf(headers, "%f\n", delay);

                                    if(strcmp(referenceStation, extractedStation) == 0 && refereDelay == 0)
                                        refereDelay = delay;


                                    coordinates = Get(c, extractedStation);
                                    if(coordinates != NULL){
                                        //station_day file
                                        sprintf(stationDayName, "%s%s_%s", result, extractedStation, extratedDay);
                                        stationDay = fopen(stationDayName, "a+");
                                        fprintf(stationDay, "%s\t", extractedYear);
                                        fprintf(stationDay, "%s\t", extractedHour);
                                        fprintf(stationDay, "%s\t", extractedMin);
                                        fprintf(stationDay, "%f\t", coordinates[0]);
                                        fprintf(stationDay, "%f\t", coordinates[1]);
                                        fprintf(stationDay, "%f\t", coordinates[2]);
                                        fprintf(stationDay, "%s\t", rms);
                                        fprintf(stationDay, "%f\n", delay);
                                        fclose(stationDay);

                                        //year_day file
                                        sprintf(yearDayName, "%s%s_%s", result, extractedYear, extratedDay);
                                        yearDay = fopen(yearDayName, "a+");
                                        fprintf(yearDay, "%s\t", extractedStation);
                                        fprintf(yearDay, "%s\t", extractedHour);
                                        fprintf(yearDay, "%s\t", extractedMin);
                                        fprintf(yearDay, "%f\t", coordinates[0]);
                                        fprintf(yearDay, "%f\t", coordinates[1]);
                                        fprintf(yearDay, "%f\t", coordinates[2]);
                                        fprintf(yearDay, "%s\t", rms);
                                        fprintf(yearDay, "%f\n", delay);
                                        fclose(yearDay);

                                        //year_day_hour_min file
                                        if((hour[0] != '\0' && (strcmp(hour, extractedHour) == 0)) && (min[0] != '\0' && (strcmp(min, extractedMin) == 0))){
                                            sprintf(timeName , "%s_%s_%s", yearDayName, hour, min);
                                            time = fopen(timeName, "a+");
                                            fprintf(time, "%s\t", extractedStation);
                                            fprintf(time, "%f\t", coordinates[0]);
                                            fprintf(time, "%f\t", coordinates[1]);
                                            fprintf(time, "%f\t", coordinates[2]);
                                            fprintf(time, "%s\t", rms);
                                            fprintf(time, "%f\n", delay);
                                            fclose(yearDay);
                                        }
[.....]

3 个答案:

答案 0 :(得分:2)

你没有向我们展示足够的内容,所以这纯粹是一种猜测,但你读入extractedHour的输入可能是三个字符长,并且你已经将数组定义为3个字符,没有任何空间对于NUL终结者。

你可能在min之后立即定义了extractedHour,所以当你写完extractedHour的末尾时,它最终将NUL终结符写入下一个内存,这恰好发生在是min

答案 1 :(得分:1)

如果没有更多信息,我的猜测是locDayFile包含一个超过3个字节的字符串。当你进行fscanf调用时,它会覆盖比你想象的更多的内存。尝试为extractHour分配一个更大的缓冲区(而不是3,使它像64),让我们知道会发生什么。如果这解决了问题,你可能需要首先修复你的locDayFile,然后修复你的fscanf调用,而不是使用%s,使用%2s,这告诉scanf(和它的变种)你只希望它读取一个字符串最多#2个字符。这样可以避免缓冲区溢出。另一个选择是使用%as ...用于分配字符串(scanf将分配它存储字符串所需的许多字节)。

示例:

char *str;
fscanf(in_file, "%as", &str);  //Notice the & here!
//Not covered is calling free(str)
//But you must check if fscanf was successful
//before freeing str

示例2:

char str[3];
fscanf(in_file, "%2s", str);  //Notice this doesn't use &
//No need to deallocate, and it will not buffer overrun on you!

如果这不能解决您的计划问题,请向我们提供更多信息。

答案 2 :(得分:0)

对不起,我只能发表文体评论。

1)分而治之:将代码分解为逻辑函数,每个函数只做一件事。这样也可以更容易地测试单独的部件而不会受到太多干扰。

2)feof()没有按照你的想法做到。

3)如果您首先读取整行(例如使用fgets())并将其拆分为字段,则解析文本文件会更容易。它也不易受缓冲区溢出的影响。

4)gets()是灾难的秘诀。 scanf()就是你正在使用它的形式。