使用fscanf从文件读取时内存中的随机字符

时间:2015-09-23 19:28:56

标签: c memory random character scanf

public partial class QuoteOverrideRequestStatus : BaseEntity
{
    public QuoteOverrideRequestStatus() { }

    public virtual string Name { get; set; }
    public virtual int DisplayOrder { get; set; }
}

结果数组具有内存中的随机字符,这些字符在文件中不存在。有什么方法可以阻止这种情况吗?

3 个答案:

答案 0 :(得分:1)

代码中存在两个问题。

首先,您使用fscanf来阅读文件,而不是fgets。格式为fscanf的{​​{1}}将从文件中读取一个字。 "%s"读取一行。

第二个问题是使用fgets的最后一个for循环。在32位计算机上,sizeof(array)为100 * 4 = 400.您想要的是计算从文​​件中读取的行数,然后在sizeof(array)循环中使用该计数

考虑到这一点,我在这里编写代码

for

该行

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

int main( void )
{
    char *array[100];
    char string[80];
    FILE *fp;

    if ( (fp = fopen( "file.txt" , "r")) == NULL )
    {
        printf( "File not found\n" );
        exit( 1 );
    }

    int count = 0;
    while ( fgets( string, sizeof(string), fp ) != NULL )
    {
        string[strcspn(string,"\n")] = '\0';
        if ( count < 100 )
        {
            array[count] = strdup( string );
            count++;
        }
    }

    fclose( fp );

    for ( int k = 0; k < count; k++ )
        printf( "the element at %d is: %s\n", k, array[k] );
}

从字符串中删除换行符(如果有)。这是必要的,因为string[strcspn(string,"\n")] = '\0'; 将保留换行符。

答案 1 :(得分:1)

  1. 如果您想阅读文字行,请使用:

    fgets(line, sizeof(line), file);
    
  2. 如果一行可以包含80个字符,则需要将line定义为至少为81个字符的数组 - 以便为终止提供额外的空间空字符。

    char line[81];
    
  3. 您需要存储读取的行数,以便在写出行时,不要尝试写入比读取更多的行。确保您不会读取array能够持有的行数。

    int numLinesRead = 0;
    if (file) {
        int k = 0;
        while (fscanf(file, "%s", string)!=EOF && k < 100 ){
            array[k] = strdup(string);
            k++;     
        }                            
        fclose(file);
        numLinesRead = k;
    }
    
  4. 不要写任何超过读取的行数。

    for(int k = 0; k<numberOfLinesRead; k++){
        printf("the element at %d is: %s\n", k, array[k]);
    } 
    

答案 2 :(得分:0)

此代码中有几个问题......

    char *array[100];
    char string[80];

到目前为止,非常好,现在让我们来看看:

        int k = 0;
        while (fscanf(file, "%s", string)!=EOF){
            array[k] = strdup(string);
            k++;
        }                            

问题在这里:

  1. 您不检查k。如果k达到100
  2. ,则应停止此操作
  3. 检查EOF是错误的。其他事情也可能失败。
  4. %s只会读到下一个空格,可能不是你想要的。
  5. 只要有非空格字符,
  6. %s就会读取,因此在给定恶意输入的情况下溢出string
  7. 正确的版本会例如看起来像这样:

            int k = 0;
            while (k < 100 && fgets(string, 80, file)){
                array[k] = strdup(string);
                k++;
            }                            
    

    然后到下一个有问题的部分:

        for(int k = 0; k<sizeof(array); k++){
            printf("the element at %d is: %s\n", k, array[k]);
        }
    

    sizeof()为您提供其参数的字节大小。数组的大小固定,实际存储的元素数量无关紧要。元素是指针,所以占用超过1个字节。

    正确版本:

        int lines = 0; // nothing read
        if (file) {
            int k = 0;
            while (k < 100 && fgets(string, 80, file)){
                array[k] = strdup(string);
                k++;
            }                            
            fclose(file);
            lines = k;
        }
    
        for(int k = 0; k<lines; k++){
            printf("the element at %d is: %s\n", k, array[k]);
        }