简体   繁体   English

C中的fscanf,带无空格的文本文件

[英]fscanf in C with a text file with no spaces

I have a text file with names that looks as follows: 我有一个名称如下的文本文件:

"MARY","PATRICIA","LINDA","BARBARA","ELIZABETH","JENNIFER","MARIA","SUSAN","MARGARET", “MARY”, “PATRICIA”, “琳达”, “BARBARA”, “伊丽莎白”, “JENNIFER”, “MARIA”, “SUSAN”, “霭”,

I have used the following code to attempt to put the names into an array: 我已经使用以下代码尝试将名称放入数组:

char * names[9];
int i = 0;
FILE * fp = fopen("names.txt", "r");

for (i=0; i < 9; i++) {
  fscanf(fp, "\"%s\",", names[i]);
}

The program comes up with a segmentation fault when I try to run it. 当我尝试运行该程序时,出现了段错误。 I have debugged carefully, and I notice that the fault comes when I try and read in the second name. 我已经进行了仔细的调试,当我尝试读取第二个名称时,我注意到故障出在这里。

Does anybody know why my code isn't working, and also why the segmentation fault is happening? 有人知道我的代码为什么不起作用,以及为什么分段错误正在发生吗?

You have undefined behavior in your code, because you don't allocate memory for the pointers you write to in the fscanf call. 您的代码中有未定义的行为 ,因为您没有为在fscanf调用中写入的指针分配内存。

You have an array of nine uninitialized pointers, and as they are part of a local variable they have an indeterminate value, ie they will point to seemingly random locations. 您有九个未初始化指针的数组,并且由于它们是局部变量的一部分,因此它们具有不确定的值,即它们将指向看似随机的位置。 Writing to random locations in memory (which is what will happen when you call fscanf ) will do bad things. 写入内存中的随机位置(这会在您调用fscanf时发生)会做坏事。

The simplest way to solve the problem is to use an array of arrays, like eg 解决问题的最简单方法是使用数组数组,例如

char names[9][20];

This will gives you an array of nine arrays, each sub-array being 20 characters (which allows you to have names up to 19 characters long). 这将为您提供9个数组的数组,每个子数组为20个字符(允许您使用最多19个字符的名称)。

To not write out of bounds, you should also modify your call so that you don't read to many characters: 为了不超出范围,您还应该修改通话,以免读取太多字符:

fscanf(fp, "\"%19s\",", names[i]);

There is however another problem with your use of the fscanf function, and that is that the format to read a string, "%s" , reads until it finds a whitespace in the input (or until the limit is reached, if a field width is provided). 但是,使用fscanf函数还有另一个问题,那就是读取字符串"%s"的格式将一直读取,直到找到输入中的空白为止(或者直到达到限制为止,如果字段宽度为提供)。

In short: You can't use fscanf to read your input. 简而言之:您不能使用fscanf来读取您的输入。

Instead I suggest you read the whole line into memory at once, using fgets , and then split the string on the comma using eg strtok . 相反,我建议您使用fgets将整行立即读取到内存中,然后使用例如strtok在逗号上分割字符串。


One way of handling arbitrarily long lines as input from a file (pseudoish-code): 一种处理任意长行作为文件输入的方法(伪代码):

#define SIZE 256

size_t current_size = SIZE;
char *buffer = malloc(current_size);
buffer[0] = '\0';  // Terminator at first character, makes the string empty

for (;;)
{
    // Read into temporary buffer
    char temp[SIZE];
    fgets(temp, sizeof(temp), file_pointer);

    // Append to actual buffer
    strcat(buffer, temp);

    // If last character is a newline (which `fgets` always append
    // if it reaches the end of the line) then the whole line have
    // been read and we are done
    if (last_character_is_newline(buffer))
        break;

    // Still more data to read from the line
    // Allocate a larger buffer
    current_size += SIZE;
    buffer = realloc(buffer, current_size);

    // Continues the loop to try and read the next part of the line
}

// After the loop the pointer `buffer` points to memory containing the whole line

[ Note: The above code snippet doesn't contain any error handling.] [ 注意:上面的代码段不包含任何错误处理。]

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

int main(void) {
    char *names[9], buff[32];
    int i = 0;
    FILE *fp = fopen("names.txt", "r");

    for(i = 0; i < 9; i++) {
        if(1==fscanf(fp, "\"%31[^\"]\",", buff)){//"\"%s\"," does not work like that what you want
            size_t len = strlen(buff) + 1;
            names[i] = malloc(len);//Space is required to load the strings of each
            memcpy(names[i], buff, len);
        }
    }
    fclose(fp);
    //check print & deallocate
    for(i = 0; i< 9; ++i){
        puts(names[i]);
        free(names[i]);
    }
    return 0;
}

try this... 尝试这个...

for (i=0; i < 9; i++) 
{
   names[i]=malloc(15);// you should take care about size
   fscanf(fp, "\"%s\",", names[i]);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM