Как использовать аргумент командной строки для ввода данных и преобразования данных в верхний регистр - PullRequest
0 голосов
/ 06 ноября 2018

Я пытаюсь выяснить, как мне использовать данные, которые я ввел в командной строке, и использовать их для преобразования моих данных в заглавные буквы. Я очень новый в C. Вот код. Может кто-нибудь сказать мне, что я сделал не так? Я пытаюсь преобразовать любые строчные слова в прописные с помощью динамического выделения памяти.

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


int main(int argc, char*argv[]){
int i;
char * string;
//Dynamic Memory Allocation

string = (char*)malloc(argc * sizeof(char));
for (i=1; i<argc; i++){
printf("%s\n",argv[i]);

}       

strcpy(string, argv[i]);

for (i = 1; string[i] != '\0'; i++){
    if(string[i] >= 'a' && string[i] <= 'z'){
        string[i] = string[i] - 32;
    }
}

return 0;
}

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Может кто-нибудь сказать мне, что я сделал не так?

Да. Различные проблемы.

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;
    }
  }
}
0 голосов
/ 06 ноября 2018

Есть несколько ошибок

  1. Во-первых

    string = (char*)malloc(argc * sizeof(char));
    

argc дает количество параметров, а не длину строки. Чтобы получить длину параметра argv[1], используйте strlen

len = strlen(argv[1]);
string = malloc (len+1);
  1. Во-вторых

    strcpy(string, argv[i]);
    

argv[0] - обычно имя программы. argv[1] выдаст имя первого параметра. Вы также можете добавить проверку на argc, чтобы увидеть, добавил ли пользователь никаких параметров. Если вы вводите один параметр, его можно изменить на

if (argc == 2)
{
   strcpy(string, argv[1]);
}
else
{
   //report error to user
}
  1. В-третьих

Вы ссылаетесь на индексы, начиная с 1. В C индексы начинаются с 0.

for (i = 0; string[i] != '\0'; i++){
    if(string[i] >= 'a' && string[i] <= 'z'){
        string[i] = string[i] - 32;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...