【问题标题】:How to include the spaces?如何包含空格?
【发布时间】:2014-06-29 12:39:56
【问题描述】:

我正在尝试编写一个程序,该程序从文件中获取单词并将其放入动态数组中。但是,当我尝试运行我的代码时,程序会复制所有内容,除了空格。我该如何解决这个问题?

这是一个测试,它有效吗?

但我得到以下信息:

这测试有效吗?

char** getWords(char* filename, int* pn){
char** tmp = (char**)malloc( 1000*sizeof(char));
int *temp=(int*)malloc(1000*sizeof(int);
int c;
int counter = 0;



FILE* fileInput = fopen(filename, "r");
if(fileInput == NULL){
    return tmp; // return if file open fails
}


while((c=fgetc(fileInput)) != EOF){
    result = fscanf(fileInput, "%c", &c); //try to read a character
    if(isalpha(c)){ //chararect alphabetical
    tmp[counter] = c; // safe int to array
    counter ++;
    printf("%c", c); fflush(stdout);
    }
    else{ // if read not succesfull
        fscanf(fileInput, ""); // needs to scan anything not a character
    }
    if(counter > 100){ // to not exceed the array
        break;
    }
    if(feof(fileInput)){ // to check if at the end of the file
        break;
    }

}
fclose(fileInput); // closing file
*pn = counter;
return tmp;}

我的主要功能:

int main(int argc, char* argv[]){
int n;
char** a = getWords("opdracht_4_5.c", &n);
if (a != NULL){
    puts("gevonden woorden:");
    for (int i = 0;i < n; i++){
        printf("%3d %s\n",i,a[i]);
    }
    for (int i = 0;i < n; i++){
        free(a);
    }
    free(a);
}
return (EXIT_SUCCESS);

}

【问题讨论】:

  • 这是学习调试的绝佳机会。你在 Linux 上吗?然后使用-g 编译您的程序并运行gdb --args ./mytool 并输入r
  • 一个不错的调试入门可以在这里找到:ericlippert.com/2014/03/05/how-to-debug-small-programs
  • 这段代码有很多错误。
  • 对于初学者:char s[100]; 在第一次使用之前未初始化。
  • 我已经初始化了 char 并删除了一些 **

标签: c arrays file


【解决方案1】:

您的代码存在很多问题。这是一个开始:

  • 你没有测试fopen()的返回值。
  • 你没有测试malloc()的返回值。
  • 您将fgetc() 的返回值分配给char 类型的变量。普通charsigned charunsigned char 兼容。为了区分字符和EOF(负数),fgetc() 函数返回转换为 unsigned char(或 EOF)的字符。您需要测试EOF然后将值转换为普通的char
  • is...() 函数需要一个 int 参数,其值在 unsigned charEOF 的范围内。如果你有一个普通的char,你首先必须将它转换为unsigned char,或者你可以将fgetc()的返回值直接传递给isalpha()
  • 您尝试将一个长度为零的char 数组(temp) 附加到一个未初始化的char 数组(s),并且您没有测试目标数组中是否有足够的空间。这被破坏的原因比我想列举的要多。
  • 您为一个包含 1000 个指向 char 的指针的数组分配内存,但您从未为 char 指针本身分配内存。
  • 您尝试将缓冲区 (s) 附加到未初始化的指针 (*tmp)。
  • 您调用 strlen() 处理非空终止的内容。
  • 您永远不会返回数组的长度。
  • 您调用了许多尚未声明的函数。

【讨论】:

    【解决方案2】:

    这将读取文件,将每个单词放入一个数组中

    #include<stdlib.h>
    #include<stdio.h>
    #include<string.h>
    
    char** getWords(char* filename, int* pn){
        char input[100]; // array to hold each word
        char** tmp; // double pointer
        int counter = 0;
        int words = 0;
        int c;
    
        tmp = malloc( (*pn)*sizeof(char*)); // allocate pointers for number of words
        if ( tmp == NULL) {
            printf ( "malloc failed\n");
            exit (1);
        }
        FILE* fileInput = fopen(filename, "r");
        if(fileInput == NULL){
            printf ( "file open failed\n");
            *pn = 0; // no words entered
            return tmp; // return if file open fails
        }
    
        while(( c = fgetc(fileInput)) != EOF){
            if( isalnum(c)){ // is alpha or number
                input[counter] = c; // save to array
                input[counter + 1] = '\0'; // save a \0 to the end to make a string
                counter ++;
            }
            else{ // not alpha or number
                if ( counter > 0) { // if there are characters, save the word
                    tmp[words] = malloc ( strlen ( input) + 1); // memory for this word
                    strcpy ( tmp[words], input); // copy the word to the array
                    words++;
                    counter = 0;
                    if ( words >= *pn) { // got all the words wanted
                        break;
                    }
                }
            }
            if(counter > 98){ // too many characters for input, start a new word
                tmp[words] = malloc ( strlen ( input) + 1);
                strcpy ( tmp[words], input);
                words++;
                counter = 0;
                if ( words >= *pn) {
                    break;
                }
            }
        }
        fclose(fileInput); // closing file
        *pn = words; // save number of words
        return tmp;
    }
    
    int main(int argc, char* argv[]){
        int n;
        int i;
    
        printf ( "enter the number of words to obtain\n");
        scanf ( "%d", &n);
        char** a = getWords("opdracht_4_5.c", &n);
        if (a != NULL){
            puts("gevonden woorden:");
            for ( i = 0;i < n; i++){
                printf("%3d %s\n",i,a[i]);
            }
            for ( i = 0;i < n; i++){
                free(a[i]); // free each word
            }
            free(a); // free the pointer to the words
        }
        return (EXIT_SUCCESS);
    }
    

    我使用的输入文件的前两行是这些
    #include&lt;stdio.h&gt;
    #include&lt;string.h&gt;

    我得到这个输出:

    输入要获得的字数 6 杰文登木:
    0 包括
    1 个标准输出
    2 小时
    3 包括
    4串
    5 小时

    【讨论】:

    • 由于某种原因,它一直说 isalnum 是函数的隐式声明
    • 它没有工作它仍然一个接一个地打印所有单词。没有中间的空格。
    【解决方案3】:

    这个答案还不完整

    请允许我在发表评论之前完成这个——谢谢


    如果您的代码有很多问题,我不会为您清理。不过,我想给你一些关于你的程序应该如何编码的提示:

    您的主要目标是读取文件并将内容逐字加载到数组中。

    排序是一种不正确的用法,因为这意味着您希望在将它们加载到数组后按字母顺序或其他顺序对它们进行排序。

    好的,首先,让我们弄清楚我们程序的整体操作。我们将我们的程序称为 kitten,因为它不如 cat 强大。

    为了运行我们的程序,我们假设我们在命令行上给它我们想要读取的文件名,如下所示:

    $ ./kitten somefile.txt
    

    并期望输出为:

    word1
    word2
    word3
    .
    .
    .
    wordN
    
    Total words: N
    

    那么,让我们开始吧,首先我们确保我们的用户指定了一个文件名:

    #include <stdio.h>
    
    int usage(const char *progname);
    
    int main(int argc, char *argv[])
    {
        if (argc < 2) {
            usage(argv[0]);
            return -1;
        }
        return 0;
    }
    
    int usage(const char *progname)
    {
        fprintf(stderr, "Usage is:\n\t%s filename\n", progname);        
    }
    

    现在我们知道我们的程序可以获取文件名,让我们尝试打开文本文件,如果有问题我们使用 perror 显示错误并退出程序,否则我们准备使用文件:

    #include <stdio.h>
    #include <errno.h>
    
    int usage(const char *progname);
    
    int main(int argc, char *argv[])
    {
    
        FILE *fp;
    
        if (argc < 2) {
            usage(argv[0]);
            return -1;
        }
    
        fp = fopen(argv[1], "r");
        if (!fp) {
              perror(argv[1]); /* display system error, with the filename */
              return -1;
        }
    
        /* TODO: file manipulation goes here */
    
        fclose(fp); /* close the file */
        return 0;
    }
    
    int usage(const char *progname)
    {
        fprintf(stderr, "Usage is:\n\t%s filename\n", progname);        
    }
    

    现在在 C 中,每个函数都应该只执行一项任务。这项任务应该具有人类意义。例如,如果该函数应该将单词读入一个数组,那么它应该做的就是它不应该打开文件或关闭文件,这就是为什么上面的代码没有创建一个函数来以你的方式打开文件做过。您的函数应该将FILE * 作为要读取的文件。

    因为我们使用FILE * 作为输入,所以我们将以f 开头的函数名称以符合stdio 约定。理想情况下,该函数应采用指向char *(字符串)的指针来存储单词。

    #include <stdio.h>
    #include <errno.h>
    
    int usage(const char *progname);
    size_t fload(FILE *fp, char **wordlist_p);
    
    int main(int argc, char *argv[])
    {
    
        FILE *fp;
    
        if (argc < 2) {
            usage(argv[0]);
            return -1;
        }
    
        fp = fopen(argv[1], "r");
        if (!fp) {
              perror(argv[1]); /* display system error, with the filename */
              return -1;
        }
    
        if(fload(fp, wordlist_p) < 0) {
              fprintf(stderr, "Something went wrong\n")
        }        
    
        fclose(fp); /* close the file */
        return 0;
    }
    
    int usage(const char *progname)
    {
        fprintf(stderr, "Usage is:\n\t%s filename\n", progname);        
    }
    
    size_t fload(FILE *fp, char **wordlist_p)
    {
           size_t rv = -1; /* return value */
           return rv;
    }
    

    现在我们遇到了一个概念问题。我们如何为wordlist_p 分配内存?我的意思是我们不知道文件有多大,我们也不知道文件中最大的单词有多大。

    粗略方法

    让我们先尝试一个简单的方法:

         Point to the beginning of the `wordlist_p` with a `tail_pointer`
         Read the file line by line, (we assume no hyphenation)
         For each line split the line up along white spaces, 
            Allocate space for the number of words in the `wordlist_p` array
            For each word in the split line
               Allocate space for the word itself 
               Save the pointer to the word at the tail_pointer
               Advance wordlist_p tail_pointer
            Next word
         Next Line
    

    让我们看看fload 函数在上面的这些步骤中会是什么样子,

    更多内容##

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 2011-04-13
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    相关资源
    最近更新 更多