Может кто-нибудь сказать мне, что я сделал не так?
Да. Различные проблемы.
string = (char*)malloc(argc * sizeof(char));
выделяет на основе количества аргументов (каждый из которых строка) для программы, а не для длины задействованных строк. Чтобы найти длину строки, используйте size_t len = strlen(s);
Добавьте 1 для размера строки. @ Дэвид С. Ранкин
i
в strcpy(string, argv[i])
- это то же значение, что и argc
, а затем argv[argc] == NULL
. strcpy(string, argv[i])
плохо, неопределенное поведение , так как argv[i]
не указывает на строку.
string[i] >= 'a' && string[i] <= 'z')
- слабый способ обнаружения заглавных букв. Используйте isupper()
для производительности и мобильности.
string[i] = string[i] - 32;
- слабый способ преобразования в верхний регистр. Используйте toupper()
для производительности и переносимости, а затем isupper()
не требуется.
string = (char*)malloc(argc * sizeof(char));
использует ненужное приведение. Проще кодировать правильно, просматривать и поддерживать код по размеру для указателя без ссылки, чем для типа указателя. string = malloc(sizeof *string * n);
Классический подход выделил бы массив указателей на строки и затем память для каждой строки. Затем преобразуйте их в верхний регистр, используя стандартные библиотечные функции.
// Get memory for the string pointers
char **uppercase_string = malloc(sizeof *uppercase_string * argc);
if (uppercase_string == NULL) {
fprintf(stderr, "Out of memory");
return EXIT_FAILURE;
}
// Get memory for each string and convert
for (int a=0; a< argv; a++) {
size_t length = strlen(argv[a]);
size_t size = length + 1; // strings always have a final null character.
uppercase_string[a] = malloc(sizeof *uppercase_string[a] * size);
if (uppercase_string[a] == NULL) {
fprintf(stderr, "Out of memory");
return EXIT_FAILURE;
}
for (size_t i = 0; i < length; i++) {
uppercase_string[a][i] = toupper((unsigned char) argv[a][i]);
}
uppercase_string[a][length] = '\0'; // append null character.
}
// Use uppercase_string somehow
for (int a=0; a< argv; a++) {
printf("%d <%s>\n", a, uppercase_string[a]);
}
// free resources when done
for (int a=0; a< argv; a++) {
free(uppercase_string[a]));
}
free(uppercase_string);
[Дополнительно]
C позволяет изменять строки, на которые указывает argv[i]
.
"Параметры argc и argv и строки, на которые указывает массив argv, должны изменяться программой и сохранять свои последние сохраненные значения между запуском программы и ее завершением." C11dr §5.1.2.2.1 2
Хотя я считаю, что модификация argv[]
является слабой практикой, код может отказаться от выделения памяти.
for (int a= 1; a < argc; a++) { // start at 0 it you want to convert the program name too.
char *string = argv[a];
for (size_t i = 0; string[i]; i++) {
if(string[i] >= 'a' && string[i] <= 'z') {
string[i] = string[i] - 32;
}
}
}