C- Включение realloc со строковыми указателями - PullRequest
0 голосов
/ 05 декабря 2018

Я работаю над проблемой модификации строк с динамическим распределением памяти.Применимые части моего кода следующие:

./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:

1 Ответ

0 голосов
/ 05 декабря 2018

Одна главная проблема заключается в том, как вы читаете строку:

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

Здесь pstring[b] имеет тип char *, и из-за вызова malloc он указывает нанекоторая память (если только не произойдет сбой malloc, который вы забудете проверить).

Но &pstring[b] - это указатель на указатель и имеет тип char **.Это вряд ли то, что вы хотите, и заставит scanf записывать в память где-то, что не предполагалось записывать, и даже может записывать за пределы выделенной памяти.Это, конечно, приводит к неопределенному поведению .

Как только вы решите это, вы должны помнить, что char строки в C действительно называются заканчивающиеся нулем строки байтов . null-terminator - это то, что все стандартные строковые функции ищут, чтобы найти конец строки.Конечно, это означает, что строка для x символов требует места для x + 1, чтобы соответствовать терминатору.Так что, если пользователь говорит, что он или она хочет строку длиной 6 (например), а затем вводит foobar в качестве входных данных, ему нужно место для 7 символов с терминатором.Эта проблема терминатора (или, скорее, не хватает места для нее) у вас есть и в других местах (например, функция strcopy).

Ваш scanf вызов также не мешает пользователю ввестиСтрока длиннее, что сказал пользователь.Если пользователь сказал, что строка должна быть 3 символов, но затем введите foobar, это будет писать за пределами.К сожалению, нет способа решить эту проблему только с scanf, так как модификатор ширины поля должен быть частью строки формата.Вы можете использовать функцию scanf_s, которая решает эту проблему, но она не обязательна для спецификации C и требует, чтобы вы определили конкретный макрос, чтобы он был доступен, если у реализации его есть (см. E..g thisscanf и семейный номер для получения более подробной информации).В противном случае вам нужно программно сконструировать строку формата, включающую в себя ширину поля.

Вы также do free(pstring), что недопустимо, поскольку вы сами не выделяли pstring, этомассив.Вам нужно перебрать все строки в массиве pstring и free их.Попытка передать указатель, не возвращенный malloc (и др.), На free также приводит к неопределенному поведению .

Наконец, в C вам не следует приводить результатиз malloc (и связанных с ними функций) .

...