【问题标题】:C- Incorporating realloc with string pointersC- 将 realloc 与字符串指针结合
【发布时间】:2019-05-06 16:38:20
【问题描述】:

我正在处理有关使用动态内存分配修改字符串的问题。我的代码的适用部分如下:

./dma 5
    #include <stdio.h>
    #include <stdlib.h>

char* strcopy(char* destination, char* source);
char *strconcat(char* destination, char* source);

int main(int argc, char *argv[]) {

int cmd, a=1, b, length_of_str, n, n2;
char* pstring[atoi(argv[1])];

for (b=0; b<atoi(argv[1]); b++) {
    printf("Enter the length of string %d: ", b+1);
    scanf("%d", &length_of_str);
    pstring[b]=(char *)malloc(length_of_str*sizeof(char));
    printf("Please enter string %d: ", b+1);
    scanf("%s", &pstring[b]);
}

while (a!=0) {
printf("Your strings are: \n");
for (b=0; b<atoi(argv[1]); b++) {
    printf("String number %d - \"%s\"\n", b+1, &pstring[b]);
}

printf("Options:\n");
printf("1 - Find string length\n");
printf("2 - Compare strings\n");
printf("3 - Copy strings\n");
printf("4 - Concatenate strings\n");
printf("5 - Quit\n");
printf("Please enter your option: ");
scanf("%d", &cmd);

switch (cmd) {

case 3:
    printf("Enter the number of the source string: ");
    scanf("%d", &n); 
    printf("Enter the number of the destination string: ");
    scanf("%d", &n2);
    strcopy(pstring[n-1], pstring[n2-1]);
    break;
case 4:
    printf("Enter the number of the source string: ");
    scanf("%d", &n); 
    printf("Enter the number of the destination string: ");
    scanf("%d", &n2);
    strconcat(pstring[n-1], pstring[n2-1]);
    break;
case 5:
    a=0;
    break;
default:
    printf("Invalid Option.\n");
    break;
}
}

free(pstring);
return 0; 
}
char* strcopy(char* destination, char* source) {
destination=(char *)realloc(*source, sizeof(char)*strlength(destination));
for (; *source!='\0'; source++) {
    *destination=*source;
    destination++;
    }
*destination='\0';
return destination;
}

char* strconcat(char* destination, char* source) {
destination=(char *)realloc(*source, sizeof(char)*strlength(destination));
for (; *destination!='\0'; destination++) {
    }
for (; *source!='\0'; source++) {
    *destination=*source;
    destination++;
    }
*destination='\0';
return destination;
}

我需要将 realloc 合并到我的连接和复制函数中(这应该没问题,因为它们在单独的问题中工作)。我尝试了多种方法,也尝试了不同的语法,但我似乎只遇到分段错误或无效指针。我究竟应该如何合并 realloc?预期结果应如下所示:

Your strings are:
String number 1 – “first”
String number 2 – “second”
String number 3 – “third”
String number 4 – “fourth”
String number 5 – “fifth”
Options:
1 – Find string length
2 – Compare strings
3 – Copy strings
4 – Concatenate strings
5 – Quit
Please enter your option: 3
Enter the number of the source string: 2
Enter the number of the destination string: 5
Your strings are:
String number 1 – “first”
String number 2 – “second”
String number 3 – “third”
String number 4 – “fourth”
String number 5 – “second”
Options:
1 – Find string length
2 – Compare strings
3 – Copy strings
4 – Concatenate strings
5 – Quit
Please enter your option:

【问题讨论】:

  • 这些函数返回一个字符串,但您对该函数的调用不会存储返回的字符串。此外,您在 strconcat 中的 realloc 似乎使源字符串成为目标字符串的大小,而不是两个字符串的大小。
  • 更不用说如果atoi(argv[1]) 失败了。 atoi 提供零错误报告。请改用 strtol 并在创建指针的 VLA 之前验证转换。

标签: c string pointers dynamic-memory-allocation


【解决方案1】:

一个主要问题是你如何读取字符串:

scanf("%s", &pstring[b])

这里pstring[b]char * 类型,并且由于malloc 调用它指向一些内存(除非malloc 失败,您忘记检查)。

但是 &amp;pstring[b] 是一个指向指针的指针,并且是char ** 类型。这几乎不是您想要的,并且会导致scanf 写入不应该写入的内存,甚至可以写入超出分配内存的范围。这当然会导致undefined behavior

一旦你解决了这个问题,你需要记住 C 中的 char 字符串实际上称为 null-terminated 字节字符串。 null-terminator 是所有标准字符串函数寻找字符串结尾的东西。当然,这意味着x 字符的字符串需要x + 1 的空间以适应终止符。因此,如果用户说他或她想要一个长度为6 的字符串(例如),然后将foobar 作为输入,则需要为带有终止符的7 字符留出空间。这个终结符问题(或者说缺少为其分配空间)在其他地方也有(比如strcopy 函数)。

您的scanf 调用也不会妨碍用户输入用户所说的更长的字符串。如果用户说字符串应该是3字符,然后输入foobar,那会写越界。不幸的是,仅使用scanf 无法解决此问题,因为字段宽度修饰符必须是格式字符串的一部分。您可以使用解决此问题的scanf_s 函数,但它不是 C 规范强制要求的,并且需要您定义一个特定的宏以便在实现时可用(参见例如this scanf and family reference for细节)。否则,您需要以编程方式构造格式字符串以包含字段宽度。

free(pstring)这是无效的,因为你没有分配pstring本身,它是一个数组。您确实需要遍历数组pstringfree 中的所有字符串in。试图将malloc(等)未返回的指针传递给free 也会导致未定义的行为

最后,在 C 中你 should not cast the result of malloc (and related functions).

【讨论】:

    猜你喜欢
    • 2020-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 2014-03-08
    • 2011-03-13
    • 2012-07-29
    相关资源
    最近更新 更多