C语言 将 C 中的字符串拆分为每个空格

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4513316/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 07:24:02  来源:igfitidea点击:

Split string in C every white space

c

提问by redsolja

I want to write a program in C that displays each word of a whole sentence (taken as input) at a seperate line. This is what i have done so far:

我想用 C 编写一个程序,在单独的行中显示整个句子的每个单词(作为输入)。这是我到目前为止所做的:



void manipulate(char *buffer);
int get_words(char *buffer);

int main(){
    char buff[100];

    printf("sizeof %d\nstrlen %d\n", sizeof(buff), strlen(buff));   // Debugging reasons

    bzero(buff, sizeof(buff));

    printf("Give me the text:\n");
    fgets(buff, sizeof(buff), stdin);

    manipulate(buff);
    return 0;
}

int get_words(char *buffer){                                        // Function that gets the word count, by counting the spaces.
    int count;
    int wordcount = 0;
    char ch;

    for (count = 0; count < strlen(buffer); count ++){
        ch = buffer[count];
        if((isblank(ch)) || (buffer[count] == '
char * strtok ( char * str, const char * delimiters );
')){ // if the character is blank, or null byte add 1 to the wordcounter wordcount += 1; } } printf("%d\n\n", wordcount); return wordcount; } void manipulate(char *buffer){ int words = get_words(buffer); char *newbuff[words]; char *ptr; int count = 0; int count2 = 0; char ch = '\n'; ptr = buffer; bzero(newbuff, sizeof(newbuff)); for (count = 0; count < 100; count ++){ ch = buffer[count]; if (isblank(ch) || buffer[count] == '
/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}
'){ buffer[count] = '
const char* find(const char* s,
                 const char* e,
                 int (*pred)(char))
{
    while( s != e && !pred(*s) ) ++s;
    return s;
}

void split_on_ws(const char* s,
                 const char* e,
                 void (*callback)(const char*, const char*))
{
    const char* p = s;
    while( s != e ) {
        s = find(s, e, isspace);
        callback(p, s);
        p = s = find(s, e, isnotspace);
    }
}

void handle_word(const char* s, const char* e)
{
    // handle the word that starts at s and ends at e
}

int main()
{
    split_on_ws(some_str, some_str + strlen(some_str), handle_word);
}
'; if((newbuff[count2] = (char *)malloc(strlen(buffer))) == NULL) { printf("MALLOC ERROR!\n"); exit(-1); } strcpy(newbuff[count2], ptr); printf("\n%s\n",newbuff[count2]); ptr = &buffer[count + 1]; count2 ++; } } }


Although the output is what i want, i have really many black spaces after the final word displayed, and the malloc() returns NULL so the MALLOC ERROR! is displayed in the end. I can understand that there is a mistake at my malloc() implementation but i do not know what it is.

尽管输出是我想要的,但在显示的最后一个单词之后我确实有很多空格,并且 malloc() 返回 NULL 所以 MALLOC 错误!显示在最后。我可以理解我的 malloc() 实现有一个错误,但我不知道它是什么。

Is there another more elegant - generally better way to do it?

还有另一种更优雅 - 通常更好的方法吗?

Thanks in advance.

提前致谢。

回答by Hortinstein

http://www.cplusplus.com/reference/clibrary/cstring/strtok/

http://www.cplusplus.com/reference/clibrary/cstring/strtok/

Take a look at this, and use whitespace characters as the delimiter. If you need more hints let me know.

看看这个,并使用空格字符作为分隔符。如果您需要更多提示,请告诉我。

From the website:

从网站:

void printWords(const char *string) {
    // Make a local copy of the string that we can manipulate.
    char * const copy = strdup(string);
    char *space = copy;
    // Find the next space in the string, and replace it with a newline.
    while (space = strchr(space,' ')) *space = '\n';
    // There are no more spaces in the string; print out our modified copy.
    printf("%s\n", copy);
    // Free our local copy
    free(copy);
}

On a first call, the function expects a C string as argument for str, whose first character is used as the starting location to scan for tokens. In subsequent calls, the function expects a null pointer and uses the position right after the end of last token as the new starting location for scanning.

Once the terminating null character of str is found in a call to strtok, all subsequent calls to this function (with a null pointer as the first argument) return a null pointer.

Parameters

  • str
    • C string to truncate.
    • Notice that this string is modified by being broken into smaller strings (tokens). Alternativelly [sic], a null pointer may be specified, in which case the function continues scanning where a previous successful call to the function ended.
  • delimiters
    • C string containing the delimiter characters.
    • These may vary from one call to another.

Return Value

A pointer to the last token found in string. A null pointer is returned if there are no tokens left to retrieve.

Example

在第一次调用时,该函数需要一个 C 字符串作为 str 的参数,其第一个字符用作扫描标记的起始位置。在随后的调用中,该函数需要一个空指针,并使用最后一个标记结束后的位置作为新的扫描起始位置。

一旦在对 strtok 的调用中找到 str 的终止空字符,对该函数的所有后续调用(以空指针作为第一个参数)都将返回空指针。

参数

  • 字符串
    • 要截断的 C 字符串。
    • 请注意,此字符串通过分解为更小的字符串(标记)进行了修改。或者[原文如此],可以指定空指针,在这种情况下,函数继续扫描先前成功调用函数的位置。
  • 分隔符
    • 包含分隔符的 C 字符串。
    • 这些可能因一个呼叫而异。

返回值

指向在字符串中找到的最后一个标记的指针。如果没有要检索的标记,则返回空指针。

例子

char *newbuff[words]; /* Words is one less than the actual number,
so this is declared to be too small. */

newbuff[count2] = (char *)malloc(strlen(buffer))

回答by wilhelmtell

For the fun of it here's an implementation based on the callback approach:

为了好玩,这里有一个基于回调方法的实现:

int print_words(const char *string, FILE *f)
{
   static const char space_characters[] = " \t";
   const char *next_space;

   // Find the next space in the string
   //
   while ((next_space = strpbrk(string, space_characters)))
   {
      const char *p;

      // If there are non-space characters between what we found
      // and what we started from, print them.
      //
      if (next_space != string)
      {
         for (p=string; p<next_space; p++)
         {
            if(fputc(*p, f) == EOF)
            {
               return -1;
            }
         }

         // Print a newline
         //
         if (fputc('\n', f) == EOF)
         {
            return -1;
         }
      }

      // Advance next_space until we hit a non-space character
      //
      while (*next_space && strchr(space_characters, *next_space))
      {
         next_space++;
      }

      // Advance the string
      //
      string = next_space;
   }

   // Handle the case where there are no spaces left in the string
   //
   if (*string)
   {
      if (fprintf(f, "%s\n", string) < 0)
      {
         return -1;
      }
   }

   return 0;
}

回答by Stephen Canon

Consider using strtok_r, as others have suggested, or something like:

考虑使用strtok_r,正如其他人所建议的那样,或类似的东西:

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

    int main()
    {
        char *s;
        s = malloc(1024 * sizeof(char));
        scanf("%[^\n]", s);
        s = realloc(s, strlen(s) + 1);
        int len = strlen(s);
        char delim =' ';
        for(int i = 0; i < len; i++) {
            if(s[i] == delim) {
                printf("\n");
            }
            else {
                printf("%c", s[i]);
            }
        }
        free(s);
        return 0;
    }

回答by ephemient

malloc(0)may (optionally) return NULL, depending on the implementation. Do you realize why you may be calling malloc(0)? Or more precisely, do you see where you are reading and writing beyond the size of your arrays?

malloc(0)可能(可选) return NULL,具体取决于实现。你知道你为什么会打电话malloc(0)吗?或者更准确地说,您是否看到超出数组大小的读取和写入位置?

回答by Doddy

Something going wrong is get_words()always returning one less than the actual word count, so eventually you attempt to:

出错get_words()总是比实际字数少一个,所以最终你尝试:

char arr[50];
gets(arr);
int c=0,i,l;
l=strlen(arr);

    for(i=0;i<l;i++){
        if(arr[i]==32){
            printf("\n");
        }
        else
        printf("%c",arr[i]);
    }

count2, eventually, is always one more than the number of elements you've declared for newbuff[]. Why malloc()isn't returning a valid ptr, though, I don't know.

count2,最终,总是比你为 声明的元素数多一newbuff[]malloc()但是,我不知道为什么不返回有效的 ptr。

回答by Bartosz Milewski

You should be malloc'ing strlen(ptr), not strlen(buf). Also, your count2 should be limited to the number of words. When you get to the end of your string, you continue going over the zeros in your buffer and adding zero size strings to your array.

你应该 malloc'ing strlen(ptr),而不是 strlen(buf)。此外,您的 count2 应限制为字数。当您到达字符串的末尾时,您继续遍历缓冲区中的零并将零大小的字符串添加到数组中。

回答by asveikau

Just as an idea of a different style of string manipulation in C, here's an example which does not modify the source string, and does not use malloc. To find spaces I use the libc function strpbrk.

正如 C 中不同风格的字符串操作的想法一样,这里有一个示例,它不修改源字符串,也不使用malloc. 要查找空格,我使用 libc 函数strpbrk

##代码##

回答by Fahad Alotaibi

you can scan the char array looking for the tokenif you found it just print new lineelse print the char.

你可以扫描字符数组寻找令牌,如果你发现它只是打印新的生产线还有打印的查

##代码##

回答by razAguls deztiny

##代码##