【问题标题】:C - Reverse order of words in an array of StringsC - 字符串数组中单词的反转顺序
【发布时间】:2018-12-10 17:10:01
【问题描述】:

我做了这个程序来反转给定字符串中单词的顺序。 (而且有效)

即输出:sentence first the is This

但是,在向数组中添加另一个句子时,我被卡住了。 例如,我需要有一个数组 {"This is the first sentence", "And this is the second"} 产生作为输出:sentence first the is This , second the is this And

int main() {

    char str[] = {"This is the first sentence"};
    int length = strlen(str);

    // Traverse string from end
    int i;
    for (i = length - 1; i >= 0; i--) {
        if (str[i] == ' ') {

    // putting the NULL character at the position of space characters for 
    next iteration.
        str[i] = '\0';

        // Start from next character
        printf("%s ", &(str[i]) + 1);
        }
}

    // printing the last word
    printf("%s", str);

    return 0;
}

我是 C 的新手,所以即使解决方案很简单,我也会被卡住也就不足为奇了。任何帮助,将不胜感激!谢谢!

【问题讨论】:

标签: c arrays string reverse


【解决方案1】:

由于您已经有了以相反顺序打印一个字符串的单词的代码,我建议将其设为一个 function,它将单个字符串作为参数,即:

void print_words_reverse(char * const str) {
    // your current code here
}

然后你可以为每个字符串分别调用它:

char strings[][30] = {
    "This is the first sentence",
    "And this is the second"
};
for (int i = 0; i < sizeof(strings) / sizeof(*strings); ++i) {
    print_words_reverse(strings[i]);
}

请注意,由于您正在修改字符串(通过用 NUL 字节替换空格),因此该参数需要是可修改的,这意味着您不能使用指向字符串文字的指针来调用它(在标准 C 中),这意味着您不能简单地使用const char *strings[] = { "first", "second" }。您可以通过使您的代码不修改参数字符串来摆脱为每个字符串保留的丑陋的常量长度(此处为30)。或者,您可以为每个句子创建一个单独的 char 数组,然后使用指向这些(可修改)字符串的指针。

【讨论】:

  • 您可能还希望在最后一个单词之后打印一个换行符。
【解决方案2】:

首先,您可以尝试使用二维数组或指针数组。

其次,在您的方法中,您丢失了字符串的初始值,我不知道它有多重要。

这是我使用指针数组的快速方法。

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

static void print_word(const char *str)
{
    for (int i = 0; str[i] && str[i] != ' '; i++)
        printf("%c", str[i]);
    putchar(' ');
}

int main(void)
{
    int len;
    const char *str[] = {"This is the first sentence",
                         "And this is second", NULL};

    for (int i = 0; str[i]; i++) { 
        for (len = strlen(str[i]); len >= 0; len--) {
            if (len == 0)
                print_word(&str[i][len]);
            else if (str[i][len] == ' ') 
                print_word(&str[i][len + 1]);
        }
        putchar('\n');
    }

    printf("Initial value of array of strings [%s | %s] \n", str[0], str[1]);
    return 0;
}

输出是:

先说is This

第二个是这个和

字符串数组的初始值[这是第一句话|这是第二个]

【讨论】:

  • 我会使用const char *str 来明确指出指针指向不可修改的字符串。另外,我建议不要使用 if (len == 0 || …) len == 0 ? … : … 之类的语法——而是将其作为 if (len == 0) { … } else if (str[i][len] == ' ') { … } 之类的单独分支,或者使用 print(&amp;str[i][len == 0 ? len : len + 1])。 (后者也可能会诱使某些人使用print(&amp;str[i][len + (len != 0)]),但我也不会去那里。)还建议将print命名为更具描述性且不太可能发生冲突的名称。
【解决方案3】:

我建议您使用memcpy,但不要过多更改您的代码,这似乎可行

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

#define MAX_STRING_LENGTH 100

int main()
{
    char *str[] = {"This is the first", "And this is the second sentence"};
    const size_t NUM_STRING = sizeof(str)/sizeof(char*);
    /*%z used to print size_t variables*/
    printf("%zd strings found\n", NUM_STRING);
    int length[2];
    int i;
    for (i=0; i<NUM_STRING; i++)
    {
        length[i] = strlen(str[i]);
    }
    printf("length initialized %d %d\n", length[0], length[1]);

    // Traverse string from end
    int j = 0;
    char temp[MAX_STRING_LENGTH];
    printf("\n\n");
    for (j=0; j<NUM_STRING; j++)
    {
      /*Make sure the string respect the MAX_STRING_LENGTH limit*/
      if (strlen(str[j])>MAX_STRING_LENGTH)
      {
        printf("ERROR: string %d exceding max string length %d defined in constant "
        "MAX_STRING_LENGTH. Exiting from program.\n", j, MAX_STRING_LENGTH);
        exit(1);
      }
      //reset temporary string
      memset(temp, '\0', sizeof(temp));
      //printf("temp variable reinitialized\n");
      for (i = length[j] - 1; i >= 0; i--)
      {
        temp[i] = str[j][i];
        if (str[j][i] == ' ')
        {
          // putting the NULL character at the position of space characters for  next iteration.
          temp[i] = '\0';
          // Start from next character
          printf("%s ", &(temp[i]) + 1);
        }
      }

      // printing the last word
      printf("%s ", temp);
    }
    printf("\n");


    return 0;
}

【讨论】:

  • 您只使用了length[0],而length[j] 可能是有意使用的。您还应该检查 temp 是否足够长(或使用 C99 VLA temp[length[j] + 1])。并且memset 到零temp 是不必要的,因为你将它放在循环体之外,它甚至不能确保最后一个单词在第一次迭代之后正确终止——也许循环内的temp[length[j]] = '\0' 就足够了。
  • 您对length[j] 的看法是正确的。我假设作为练习字符串是代码中的字符串,或者与其他字符串没有什么不同:但总的来说你是对的。为什么memset 是不必要的?该程序可能无论如何都可以工作,但我认为最好对数组进行 inzialize 以避免不良影响。
  • memset 是不必要的,因为在填充之前初始化为零是不必要的。它导致了您假设它为零的错误,而这仅适用于外部循环的第一次迭代。 (这个错误现在更难发现了,但它仍然存在。)如果你真的想防御并将其设置为零(在循环之外),更简单的语法是char temp[100] = { 0 };,这也可以让编译器决定如何最好地完成它。
  • memset 是不必要的,因为在填充之前初始化为零是不必要的。:我用来填充数组的字符串实际上(它必须)更短然后数组的元素:如果我不memset 数组之后的元素,其索引大于字符串的长度,则未初始化。您对NUM_STRING 的看法是正确的,但请记住,这是一个练习,而不是答案的重点。你是对的,虽然关于 MAX_STRING_COUNT 我打算使用它然后我改变了主意。
  • 在我看来,您对memset 引起的错误是不对的:它是由for (i = length[0] - 1; i &gt;= 0; i--) 引起的:将此行更改为for (i = length[j] - 1; i &gt;= 0; i--) 似乎有效
猜你喜欢
  • 2023-03-05
  • 2010-11-03
  • 2011-11-07
  • 1970-01-01
  • 2021-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多