Массив, изменяющий первое значение без явного изменения при вызове fscanf - PullRequest
0 голосов
/ 15 сентября 2011

Я читаю значение из стандартного ввода и сохраняю его в массиве min[3], а затем приступаю к сравнению массивов. Так что min никогда не трогали перед сравнением.

После отладки я заметил, что min[0] изменяется от значения ввода до \0 при выполнении этой строки:

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

где locDayFile и extractedHour объявлены так:

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 ]

2 голосов
/ 15 сентября 2011

Вы не показали нам достаточно, так что это чисто предположение, но ввод, который вы читаете в extractedHour, вероятно, состоит из трех символов, и вы определили массив как 3 символа, не оставляя места для NUL терминатор.

Вы, вероятно, определили min сразу после extractedHour, поэтому, когда вы пишете после конца extractedHour, он заканчивает тем, что записывает терминатор NUL в следующую память, которая оказывается min.

1 голос
/ 16 сентября 2011

Если немного больше информации, я предполагаю, что 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!

Если это не исправит вашу программу, дайте нам немного больше информации.

0 голосов
/ 16 сентября 2011

Извините, я могу давать только стилистические замечания.

1) разделяй и властвуй: разделяй код на логические функции, каждая из которых выполняет только одно. Это также облегчит тестирование отдельных деталей без особых помех.

2) feof () не делает то, что вы думаете.

3) Анализ текстовых файлов проще, если вы сначала читаете целыми строками (например, с помощью fgets ()), а не разбиваете их на поля. Он также менее уязвим для переполнения буфера.

4) gets () - рецепт катастрофы. Как и функция scanf () в той форме, в которой вы ее используете.

...