1

我对 C 真的很陌生(我一直在学习 Cuda 并想学习 C,所以我可以一起运行所有东西,而不是在 Java/Python 中生成数据并将其手动复制/粘贴到我的 Cuda 程序中来玩)。我正在尝试打开一个大文件(20+gb)并解析一些数据,但因为我遇到问题,我决定先尝试解决我的问题,以验证我可以逐行打开和读取一个文件,然后在另一个文件中取一行输出的样本并尝试解析它,然后如果一切顺利,我可以简单地将它们放在一起。我设法(经过一番挣扎)让每个部分都能正常工作,但是当我将它们组合在一起时它不起作用(我在 eclipse 和 QT creator 中都试过了。QT creator 说它意外退出并且 eclipse 只是停止了......)。

这是解析部分(它完全按照我的意愿工作):

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

int main()
{
    char line[1024] = "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 4],";
    size_t len = strlen(line);
    memmove(line, line+1, len-3);
    line[len-3] = 0;
    printf("%s \n",line);


    char str[100], *s = str, *t = NULL;

    strcpy(str, line);
    while ((t = strtok(s, " ,")) != NULL) {
        s = NULL;
        printf(":%s:\n", t);
    }
    return 0;
}

如果我打印文件的每一行,变量行中的数据与我得到的数据完全相同。但是当我将它复制/粘贴到我的主程序中时,它就不起作用了(QT 什么都不显示,而 Eclipse 只显示第一行)。这段代码只是围绕上述命令的一些文件 IO 命令(while 循环中的所有内容都与上述完全相同)

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

int main() {

    char line[1024];
    FILE *fp = fopen("/Users/me/Desktop/output.txt","r");

    printf("Starting.. \n");

    int count = 0;
    int list[30]; //items will be stored here

    while(fgets(line, 1024, fp) != NULL){
        count++;
        //char line[1024] = "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 4],";
        size_t len = strlen(line);
        memmove(line, line+1, len-4);
        line[len-4] = 0;
        printf("%s \n",line);

        char *s = str, *t = NULL;

        strcpy(str, line);
        while ((t = strtok(s, " ,")) != NULL) {
            s = NULL;
            printf(":%s:\n", t);
        }
    }
    printf(" num of lines is %i \n", count);
    return 0;
}

日食输出:

Starting.. 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 4 

我无法弄清楚我做错了什么。如果有帮助,我正在使用带有 gcc 4.2 的 mac。我唯一能想到的可能是我在解析列表变量的方式上做错了,因此以后无法访问它(我不确定这是一个疯狂的猜测)。有什么我想念的吗?

编辑:如果我注释掉这段代码,它会通过文件(但不解析):

while ((t = strtok(s, " ,")) != NULL) {
    s = NULL;
    printf(":%s:\n", t);
}

该文件的内容基本上是:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 4],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 4],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 2, 2, 4],

依此类推(其中 20+gb)。

EDIT2:我只是想测试它是否与我的mac一起使用,我在centos 5上尝试了它(安装它只是为了测试),从命令行运行时我得到了同样的错误,除了它最后说的Segmentation fault。我所做的只是将上面的示例输出复制到一个文件中,然后更改上面代码中的路径并运行它。

4

2 回答 2

4

这里有两个声明line- 一个紧随其后main(),一个紧随其后whilefgets读入第一个line变量。在 while 块中,第二个line声明掩盖了第一个(因为第二个更本地化)。外部line变量——fgets读入的变量——在程序的其他任何地方都不能访问。

于 2012-05-31T22:10:09.410 回答
3

我知道了!尝试插入#include <string.h>其他包含。我不知道你为什么在<string.h>不包含它的情况下使用它,但它导致了不正确的链接。编译器发出以下警告:

test2.c:17: warning: incompatible implicit declaration of built-in function ‘strlen’
test2.c:18: warning: incompatible implicit declaration of built-in function ‘memmove’
test2.c:24: warning: incompatible implicit declaration of built-in function ‘strcpy’
test2.c:25: warning: assignment makes pointer from integer without a cast

前三个警告表明您没有包含头文件。最后一个只是表明,如果没有声明,则假定函数接受和返回整数(这是为了向后兼容古老的 C 代码)。

不要忘记fgets在行尾包含换行符。您需要通过更改len-3为来解决此问题len-4

另外,完成后不要忘记fclose文件。

此外,您的 memmove 是不必要的,因为您只需指向第二个字符:

char *moved_line = line + 1;
于 2012-05-31T22:37:55.417 回答