【问题标题】:Changing the order of some words in a string更改字符串中某些单词的顺序
【发布时间】:2017-01-08 15:36:46
【问题描述】:

我已经尝试解决这个练习一周了,但我的代码不起作用,我不明白为什么以及如何更改它。练习是: 从用户那里接收一个长度,然后接收一个字符串(str)只要'length',然后从用户那里接收一个数字(int n)。然后我需要执行函数'void ReverseNumWords(char * str,int n ). 该函数反转字符串中的前 n 个单词。例如:对于“我是你的父亲星球大战”和 n=3: '你是我的父亲星球大战'。假设单词用“ ”分隔是正确的。谢谢您的帮助!!

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

void Reverse()
{

   int len,num;
   char *str;
   printf("Please enter how many chars to allocate:\n");
   //Asking from the user the length of a string.
   scanf("%d", &len);
   //Allocating memory for the string.
   str = (char*)calloc(len, sizeof(int));
   //Making sure the allocation was successful.
   if (!str)
       printf("Error: Cannot allocate Memory\n");
   printf("Allocated %d chars\n", len);
   printf("Please enter your string:\n");
   scanf("%s", str);
   printf("Please enter how many words to reverse:\n");
   scanf("%d", &num);
   ReverseNumWords(*str, num, len);
   free(str);
}

void ReverseNumWords(char*str, int num,int len)
{

   char *sub;
   char temp;
   //Allocating memory for the string.
   sub = (char*)calloc(len, sizeof(int));
   //Making sure the allocation was successful.
   if (!sub)
       printf("Error: Cannot allocate Memory\n");
   int i, j,l;
   i = j = 0;
   for (; i < len, j <= num; i++)
       if (str[i] == '\0' || str[i] == 0)
           j++;

   for (l = 0; l < i; l++)
       sub[i] = str[i];

   for (j = 0; j < i; j++)
       temp = sub[j];
       sub[j] = sub[i - (1+j)];
       sub[i - (1+j)] = sub[j];

   reverseWords(*sub);


}

void reverseWords(char *sub)
{

   char *word_begin = sub;
   char *temp = sub;

   while (*temp)
   {
      temp++;
      if (*temp == '\0')
      {
         reverse(word_begin, temp - 1);
      }
      else if (*temp == ' ')
      {
         reverse(word_begin, temp - 1);
         word_begin = temp + 1;
      }
   } 

   reverse(sub, temp - 1);
}

void reverse(char *begin, char*sub, char *end)
{

    char temp;
    while (begin < end)
    {
        temp = *begin;
        *begin++ = *end;
        *end-- = temp;
    }
    printf("%s\n", sub);
}

【问题讨论】:

  • 首先,为什么要使用 sizeof(int) 来分配字符?
  • 你是对的!改变了它,代码仍然不起作用......我觉得有一个简单的方法来编码这个,而不是我让它变得更复杂......任何提示?你能告诉我你会怎么做才能成功解决它吗?
  • 我现在正在处理您的代码。我的第一件事是改变你阅读它的方式,我会尝试阅读字符,而不是字符串。请等一下
  • 出现段错误,我正在尝试找出原因
  • 在 VisualStudio 前花了几个小时,无法弄清楚为什么代码不起作用......

标签: c string pointers malloc calloc


【解决方案1】:

你的读取函数,应该是这样的

int len,num;
   char *str;
   printf("Please enter how many chars to allocate:\n");
   //Asking from the user the length of a string.
   scanf(" %d", &len);
   //Allocating memory for the string.
   str = (char*)malloc(sizeof(char)*(len+1));
   //Making sure the allocation was successful.
   if (!str)
       printf("Error: Cannot allocate Memory\n");

   printf("Allocated %d chars\n", len);
   printf("Please enter your string:\n");
   scanf(" %[^\n]s", str);

   printf("Please enter how many words to reverse:\n");
   scanf(" %d", &num);
   ReverseNumWords(*str, num, len);
   free(str);

因为使用 %s 阅读时,您会在找到的第一个 ' '(空格)处停止。并且您想阅读直到找到 \n(输入)。

【讨论】:

  • 感谢您的帮助,但它并没有解决问题........其他功能呢?我需要它们还是有更短的方法来解决这个问题?
  • 是的,你的 ReverseNumWords 也不对。为什么在 fin \0 或 0 时遍历字符串并将 j 加 1?如果在此之后您设置 j = 0?
  • ReverseNumWords中第一个for循环中变量j的作用是什么?
  • 哦,我不知道是否 num>
  • 但是你做了 j++ 之后就不要使用它了。
【解决方案2】:

在这一行:

str = (char*)calloc(len, sizeof(int));

这需要:

str = (char*)calloc(len, sizeof(char));

我还建议您使用malloc 为您的字符串分配内存,因为您似乎无法使用calloc()

你会这样使用它:

char *str = malloc(len+1); /* Since sizeof(char) is 1, you don't need to include it */

这也引出了你Don't need to cast the result of malloc()的事实。

很高兴看到您检查分配的返回值, 总是一件好事。

另一种读取字符串的方法:

您可以改用fgets,而不是使用scanf()stdin 读取字符串。

char *fgets(char *str, int n, FILE *stream) 从输入流中读取一行,并将字节复制到char *str,它必须指定n 字节的大小作为它可以占用的空间阈值。

关于 fget 的注意事项:

  • 在缓冲区末尾追加\n 字符。如果您愿意,可以轻松移除。
  • 出错时返回NULL。如果没有读取任何字符,最后仍然返回NULL
  • 缓冲区的大小必须为n
  • 读取指定的流。来自stdinFILE *

这是一个示例,说明如何使用它从stdin 读取一行输入:

char buffer[100]; /* statically declared buffer */

printf("Enter a string: ");
fgets(buffer, 100, stdin); /* read line of input into buffer. Needs error checking */

您还可以使用 strtokstrcat 等函数来反转和连接字符串。

这是一个字符串中包含 n 个单词的示例程序:

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

char *allocate_chars(int *len);
void number_of_words(int *num);
void read_strings(char *str, int len);
char *reversed_words(char *str, int len, int num);
char *reverse_word(char *word);

int main(void) {
    int len, num;
    char *str, *result;

    str = allocate_chars(&len);

    read_strings(str, len);

    number_of_words(&num);

    result = reversed_words(str, len, num);
    printf("Reversed string = %s\n", result);

    free(result);
    free(str);

    return 0;
}

char *allocate_chars(int *len) {
    char *str;

    printf("Enter how many chars to allocate: ");
    if (scanf("%d", len) != 1 || *len < 1) {
        printf("Invalid length.\n");
        exit(EXIT_FAILURE);
    }
    getchar();

    str = malloc(*len+1);
    if (!str) {
        printf("Cannot allocate %d bytes for string.\n", *len+1);
        exit(EXIT_FAILURE);
    }

    printf("Allocated %d chars.\n", *len+1);

    return str;
}

void number_of_words(int *num) {
    printf("Please enter how many words to reverse: ");
    if (scanf("%d", num) != 1 || *num < 0) {
        printf("Invalid number.\n");
        exit(EXIT_FAILURE);
    }
}

void read_strings(char *str, int len) {
    int slen;

    printf("Please enter your string: ");
    if (fgets(str, len, stdin) == NULL) {
        printf("Cannot create buffer.\n");
        exit(EXIT_FAILURE);
    }

    slen = strlen(str);
    if (slen > 0) {
        if (str[slen-1] == '\n') {
            str[slen-1] = '\0';
        } else {
            printf("Entered string bigger than buffer size of %d bytes.\n", len);
            exit(EXIT_FAILURE);
        }
    }

    if (!*str) {
        printf("No string entered.\n");
        exit(EXIT_FAILURE);
    }
}

char *reversed_words(char *str, int len, int num) {
    char *reversed, *word, *reversed_word;
    const char *delim = " ";
    int count = 1;

    reversed = malloc(len+1);
    if (!reversed) {
        printf("Cannot allocate %d bytes for string.\n", len+1);
        exit(EXIT_FAILURE);
    }

    *reversed = '\0';

    word = strtok(str, delim);
    while (word != NULL) {
        if (count <= num) {
            reversed_word = reverse_word(word);
            strcat(reversed, reversed_word);
            free(reversed_word);
            count++;
        } else {
            strcat(reversed, word);
        }
        word = strtok(NULL, delim);
        if (word != NULL) {
            strcat(reversed, delim);
        }
    }

    return reversed;
}

char *reverse_word(char *word) {
    char *reverse;
    int slen, str_count = 0, i;

    slen = strlen(word);

    reverse = malloc(slen+1);
    if (!reverse) {
        printf("Cannot allocate %d bytes for string.\n", slen+1);
        exit(EXIT_FAILURE);
    }

    for (i = slen-1; i >= 0; i--) {
        reverse[str_count++] = word[i];
    }
    reverse[str_count] = '\0';

    return reverse;
}

示例输入:

Enter how many chars to allocate: 50
Allocated 51 chars.
Please enter your string: Hello what a lovely day
Please enter how many words to reverse: 4

输出:

Reversed string = olleH tahw a ylevol day

【讨论】:

  • 在无数天之后,我成功地解决了这个练习,但我的代码更加“混乱”和冗长。谢谢你的解释!我从你身上学到了很多。
  • @Cbeginner 没问题。
猜你喜欢
  • 2021-02-16
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 2015-12-15
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多