【问题标题】:Memory allocation in C - Acronyms :) [closed]C中的内存分配-首字母缩略词:) [关闭]
【发布时间】:2023-04-05 23:19:01
【问题描述】:

请看下面的代码。用户应输入一个句子,代码应返回该句子的首字母缩写词。

但是,当我分配 *str 并将 N 定义为 1 时。

“三个字母缩写”>>应该是>>“t”

实时,“三个字母缩写”>>是>>“tla”

这没有意义。 请解释为什么会发生这种情况。

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

#define N 1
#define M 35

char *acronyms (char *st,  char *sentence);

int main()
{

char *str=(char*)(malloc(N*sizeof(char)));
char *sen=(char*)(malloc(M*sizeof(char)));

printf("enter... ");
gets(sen);
puts(acronyms(str, sen));

free(str);
free(sen);
    return 0;
}


char *acronyms (char *st,  char *sentence)
{
     char *p = st;
     char *q = sentence;

     if (*q !=' ') {
            *p =*q;
            p++;
     }

     while (*(q+1)) {
         if (*q==' '  &&  *(q+1)!= ' ') {
             *p = *(q+1);
             p++;
         }

        q++;
     }
     *p='\0';
     return st;
}

【问题讨论】:

  • 你有更好的输入/输出样本吗?
  • 当你malloc() 时不要忘记'\0'。如果您需要一个字符串的空间,则必须分配 2 个字节。并且永远不要使用gets(),而是使用fgets()
  • 请将您的纯文本显示为文本而不是图形。
  • char *str=(char*)(malloc(N*sizeof(char))); 只分配一个字节。所以唯一可以存储在那里的字符串是空字符串。这可能不是你想要的。

标签: c


【解决方案1】:

乍一看,这似乎不是很令人满意,但是一旦您了解了这 5 个概念(每个都有示例)所指向的基本原理,这个和其他类似的任务似乎会简单得多。

执行您正在尝试的操作的必要步骤:

1) 了解控制台用户输入技术 (Good example here)
2)理解字符串的定义(Good definition,explanation here。)
3)了解[c][m]alloc(...)的用法(Good discussion here... ...)
3a) ...以及何时使用它。或不。 (heap vs. stack memory)
4) 了解字符串解析技术。 (ex 1ex 2ex 3
5) 了解合法但不明智的技术,例如使用 getsin general

这些是普遍适用的技术,对包括用户输入和字符串操作在内的许多任务很有用,但不能很好地替代参考一本好的 C 书籍以提供必要的基础知识。

【讨论】:

    【解决方案2】:

    首先,你不应该使用gets()。为什么??检查this

    您仅将1 字节的内存分配给str

    char *str=(char*)(malloc(N*sizeof(char)));
    

    在函数acronyms() 中,您正在超出分配的内存进行写入。这是undefined behavior

    要获取输入句子的首字母缩写词,您可以这样做:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    #define STR_LEN 100
    
    char *acronyms (char *pstr,  char *str_acronym);
    
    int main(void) {
    
        char input_str[STR_LEN];
        char *sen = NULL;
    
        printf ("Enter:\n");
        fgets (input_str, STR_LEN, stdin);
    
        sen = malloc (strlen(input_str) + 1);
        if (sen == NULL) {
                perror ("Failed to allocate memory");
                return -1;
        }
    
        puts (acronyms(input_str, sen));
    
        free(sen);
    
        return 0;
    }
    
    char * acronyms(char *pstr,  char *str_acronym)
    {
        int count = 0, add = 1;
    
        for (int i = 0; pstr[i] != '\0'; i++) {
                if (isspace(pstr[i])) {
                        add = 1;
                        continue;
                }
                if (add) {
                        str_acronym[count] = pstr[i];
                        count++;
                        add = 0;
                }
        }
        str_acronym[count] = '\0';
    
        return str_acronym;
    }
    

    【讨论】:

      【解决方案3】:

      代码有几个问题:

      1) 只为字符串str分配一个字节:

      #define N 1
      char *str=(char*)(malloc(N*sizeof(char)));
      

      2) 使用gets(sen) 而不是fgets(sen,M+1,stdin);

      3) char *acronyms (char *st, char *sentence) 有非常有问题的逻辑。无法识别字符串的结尾,' ' 可能存在也可能不存在:

       if (*q !=' ') {
              *p =*q;
              p++;
       }
      

      【讨论】:

        【解决方案4】:

        欢迎来到未定义行为的世界!当您使用一个脱离其键的数组时,任何事情都可能发生包括预期结果。这就是这里发生的情况:您为 str 分配 1 个单字节,并写入 5 {'h', 'a, 'n', 'd', '\0'}。 [Un]幸运的是,在较低级别上,您似乎只覆盖了未使用的内存,并实际得到了结果。

        因为它是 UB,所以你不能依赖它,并且在不同环境中编译的相同源可以 SEGFAULT 或使用完全相同的输入不打印任何内容。

        正如你在评论don't use gets中所说的那样

        【讨论】:

          猜你喜欢
          • 2013-03-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-13
          • 1970-01-01
          • 2011-01-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多