【问题标题】:Read a string and store each string in the array when newline character is found找到换行符时读取一个字符串并将每个字符串存储在数组中
【发布时间】:2013-12-13 14:41:59
【问题描述】:

这个程序是基于链表的。读入一个字符串,提取所有以换行符分隔的子字符串。

输入应该是:

hello world\ngood bye\nWhat a nice day!\n\0

那么,预期的输出应该是:

[hello world]->[good bye]->[What a nice day]->

但是,当我运行程序并输入:

hello world\ngood bye\nWhat a nice day!\n\0

我的输出是:

[hello world\ngood bye\nWhat a nice day!\n\0]->

我尝试将 NULL 字符分别读取为 '\' 和 'n',但无法处理。我该如何解决它,以打印出预期的输出?


newTB(char text[]); // 功能说明

函数 newTB 分配一个新的文本缓冲区并使用数组中给出的文本初始化其内容。输入数组中的行都以“\n”结尾。整个文本以 '\0' 结尾。


char *dumpTB (TB tb);

以下函数不会改变它们的 textbuffer 参数。分配并返回一个包含给定文本缓冲区中文本的数组。文本缓冲区的每一行都需要以 '\n' 终止(这包括最后一行)。整个文本必须以“\0”结尾。释放返回数组占用的内存是调用者的责任。如果文本缓冲区中没有行,则返回 NULL。


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

typedef struct textbuffer *TB;

typedef struct textbuffer {
    char *texts;
    TB next;
} textbuffer;

char *dumpTB (TB tb) {                            // my version of dumpTB
    TB temp = malloc(sizeof(struct textbuffer));
    temp->texts = tb->texts;
    temp->next = NULL;

    return (temp->texts);
}           

TB newTB (char text[]){                                // get the array from main function
    TB newText = malloc(sizeof(struct textbuffer));    // return the node
    newText->texts = text;
    //strcpy(newText->texts,text);
    newText->next = NULL;
    return (newText);
}
void printList(TB tb){                    //print entire list
    TB curr = tb;
    while(curr != NULL){
        printf("[%s]-> ",curr->texts);
        curr = curr->next;
    }
    printf("\n");
}

int main(int argc, char * argv[]) {
    int i=0;
    int j=0;
    char str[MAX_TEXT];
    char cpy[MAX_TEXT];
    char tmp[MAX_TEXT];
    TB textList = NULL;
    TB list = NULL;
    list = textList;

    fgets(str, MAX_TEXT, stdin);           // input should be like
                                           // hello\nworld\ngood\nbye\n\0
    while(str[i] != '\0') {
        if(str[i] == '\n') {
            cpy[i] = '\0';
            strcpy(tmp,cpy);
            textList = newTB(tmp);
            list = textList;
            textList->texts = dumpTB(textList);
            //TB newList = malloc(sizeof(struct textbuffer));
            //list = textList;
           // newList->texts = textList->texts;
            textList = textList->next;
            j=0;
        }
        cpy[j++] = str[i++];
    }
    printList(list);

    return 0;
}

【问题讨论】:

  • 你想要cpy[j] = '\0'
  • '\n' 是换行符,而您的输入是两个字符,一个反斜杠 \ 和字母“n”,因此您的匹配永远不会成功。即使您确实输入了真正的换行符,您的程序也不会执行您想要的操作,因为 fgets 将在第一个换行符处停止读取,并产生“hello”。
  • 我都试过了,但还是不行..所以我应该改变哪一部分??
  • fgets 不在循环中。像这样将输入字符串作为 'hello\nworld\ngood\nbye\n\0' 在循环之外。
  • 你需要一个作品可以将\和n解释为'\n' if it.

标签: c string linked-list


【解决方案1】:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_TEXT 256

typedef struct textbuffer *TB;

typedef struct textbuffer {
    char *texts;
    TB next;
} textbuffer;

TB newTB (char text[]){
    TB newText = malloc(sizeof(struct textbuffer));
    newText->texts = strdup(text);
    newText->next = NULL;
    return newText;
}
void printList(TB tb){
    TB curr = tb;
    while(curr != NULL){
        printf("[%s]-> ",curr->texts);
        curr = curr->next;
    }
    printf("\n");
}

int main(int argc, char * argv[]) {
    int i=0;
    int j=0;
    char str[MAX_TEXT];
    char cpy[MAX_TEXT];
//  char tmp[MAX_TEXT];
    TB list    = NULL;
    TB textlist = NULL;

    fgets(str, MAX_TEXT, stdin);//E.g. hello\nworld\ngood\nbye\n\0 -> "hello\\nworld\\ngood\\nbye\\n\\0\n"

    while(str[i] != '\n' && str[i] != '\0') {
        if(str[i] == '\\'){
            if(str[i+1] == 'n') {
                cpy[j] = '\0';
                //strcpy(tmp,cpy);
                TB newList = newTB(cpy);
                if(textlist == NULL)
                    textlist = newList;
                else {
                    textlist->next = newList;
                    textlist = textlist->next;
                }
                if(list == NULL)
                    list = newList;
                j=0;
                i += 2;
            } else if(str[i+1] == '0') {
                break;
            }
        }
        cpy[j++] = str[i++];
    }
    printList(list);
    //deallocate
    return 0;
}

【讨论】:

  • 哇.. 似乎工作正常。 :) 顺便问一下,newTB 函数中的 strdup() 是什么??
  • newText->texts = strdup(text);是否与 newText->texts = (char *)malloc((strlen(text)+1)*sizeof(char)); 相同然后 newText->texts = text; ??
  • @BrianSon newText->texts = strdup(text);是否与 newText->texts = (char *)malloc((strlen(text)+1)*sizeof(char)); 相同然后 strcpy(newText->texts , text);
【解决方案2】:

我这样改变了你的主要功能:

int main(int argc, char * argv[]) {
    int i=0;
    int j=0;
    char str[MAX_TEXT];
    char cpy[MAX_TEXT];
    //char tmp[MAX_TEXT];
    char* tmp = cpy;
    TB textList = NULL;
    TB list = NULL;
    TB newList = NULL;
    //list = textList;

    //fgets(str, MAX_TEXT, stdin);           // input should be like
                                           // hello\nworld\ngood\nbye\n\0
    strcpy(str, "hello\nworld\ngood\nbye\n");

    //  ... or use a file instead of the line above:
    /*
    FILE* f = NULL;
    *str = '\0';
    f = fopen("Sample.txt", "r");
    if (!f)
        return -1;
    (void)fread(str, MAX_TEXT, 1, f);
    fclose(f);
    */

    while(str[i] != '\0') {
        if(str[i] == '\n') {
            //cpy[i] = '\0';
            //strcpy(tmp,cpy);
            //textList = newTB(tmp);
            //TB newList = malloc(sizeof(struct textbuffer));
            //list = textList;
            //newList->texts = textList->texts;
            //textList = textList->next;
            //j=0;

            cpy[j] = '\0';
            newList = newTB(tmp);
            if (textList) {
                textList->next = newList;
                textList = newList;
            }
            else
                list = textList = newList;

            tmp = &cpy[j+1];
        }
        else
        cpy[j] = str[i];

        j++; 
        i++;
    }
    cpy[j] = '\0';
    printList(list);

    // cleanup
    for (textList=list;NULL != textList;) {
        list = textList;
        textList = textList->next;
        free(list);
    }

    return 0;
}

cpy是原始字符串的副本,换行符('\n')被换行符('\0'),tmp指向@987654324中的最后一个标记@。 list 是列表的头部,textList 用作列表的队列(新元素的插入点)。此外,我将fgets 替换为strcpy,因为您不能使用fgets 来获取多个文本行,或者您可以使用文件代替更多文本。

我尽量保留您的原始代码。

【讨论】:

  • 可能是newList = newTB(cpy);?
  • 看起来不错! :) 但是,应该有一些东西可以让我输入.. 稍后,我应该输入很长的文本文件,每个节点都应该包含一个由换行符分隔的字符串..
  • 您可以随时使用文件:FILE* f = NULL; *str = '\0'; f = fopen("Sample.txt", "r"); if (!f) return -1; (void)fread(str, MAX_TEXT, 1, f); fclose(f);
  • 我认为我的解释不够好..所以我编辑了我的代码并在其中添加了一些。
  • 我看不到 fgets 作为要求,我会在一分钟后将清理代码添加到我的答案中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-04
  • 1970-01-01
  • 2020-07-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多