Объединение строки и чисел в C

#c #concatenation #strcat

Вопрос:

У меня есть программа, которая должна подсчитать количество повторяющихся символов в строке. Например, «aaabcc» должен возвращать «a3b1c2», а «aaabcccc..a» должен возвращать «a3b1c4.2a1». В настоящее время я использую sprintf для объединения строки и чисел следующим образом: sprintf(s, "%s%c%d", s, prev, count); , где s — строка, содержащая результат. Но это вызывает ошибку, так как я использую «s» в качестве входных данных, а также в качестве пункта назначения. Есть ли какой-то способ обойти это?

Это мой код прямо сейчас:

     char *s = (char *)malloc(sizeof(char) * 100);
    char prev = argv[1][0];
    if(isdigit(prev)!=0){
        printf("%s","ERROR");
        return 0;
    }
    
    int count = 1;
    for(int i=1; i<strlen(argv[1]); i  ){
        if(isdigit(argv[1][i])!=0){
            printf("%s","ERROR");
            return 0;
        }
        
        //check if same as previous letter
        if(prev==argv[1][i]){
            count  ;
        }else{
           //add letter and count to string
            //problem
            sprintf(s, "%s%c%d", s, prev, count);
            
            count = 1;
        }
        
        //update prev
        prev=argv[1][i];
    }
    
    //add it to string
    //problem
    sprintf(s, "%s%c%d", s, prev, count);
    
    //check if result is smaller than input
    if(strlen(s) > strlen(argv[1])){
        printf("%sn", argv[1]);
    }else{
        printf("%sn", s);
    }
    free(s);
 

Комментарии:

1. Просто используйте другую строку в качестве вывода, а затем скопируйте ее обратно в s with strcpy() .

2. Или напишите в другую строку, а затем используйте strcat() ее для добавления s .

3. @Barmar Ты имел в виду что-то подобное? sprintf(t, "%c%d", prev, count); strcat(s,t); t = null;

4. Да, но если t он динамически распределяется, вам нужно использовать free(t); , а не просто присваивать значение null.

5. Использование s в качестве цели и источника вызывает неопределенное поведение и нарушает restrict квалификатор. Любой результат является действительным.

Ответ №1:

Используйте другой буфер для sprintf() , а затем объедините s с strcat() .

Убедитесь, что вы инициализируете s пустую строку после ее выделения.

Вместо того , чтобы выделять жестко заданный размер s , выделите строку, достаточно большую для наихудшего случая (каждый символ повторяется только один раз, так что это так a1b1c1... ).

temp может быть короткой строкой фиксированного размера, так как она должна содержать только длину одного прогона.

 char *s = malloc(strlen(argv[1]) * 2   1);
s[0] = '';
char temp[20];
char prev = argv[1][0];
if(isdigit(prev)!=0){
    printf("%s","ERROR");
    return 0;
}
    
int count = 1;
for(int i=1; i<strlen(argv[1]); i  ){
    if(isdigit(argv[1][i])!=0){
        printf("%s","ERROR");
        return 0;
    }
        
    //check if same as previous letter
    if(prev==argv[1][i]){
        count  ;
    }else{
        //add letter and count to string
        sprintf(temp, "%c%d", prev, count);
        strcat(s, temp);
            
        count = 1;
    }
        
    //update prev
    prev=argv[1][i];
}
    
//add it to string
sprintf(temp, "%s%c%d", prev, count);
strcat(s, temp);
    
//check if result is smaller than input
if(strlen(s) > strlen(argv[1])){
    printf("%sn", argv[1]);
}else{
    printf("%sn", s);
}
free(s);
 

Ответ №2:

Советы в комментариях и другие ответы дают вам хорошее руководство о том, как управлять строками, которые вы динамически распределяете с помощью malloc. Но вы можете упростить всю свою программу, даже не выделяя строку и не используя sprintf.

Подумайте об этом:

 int lastChar = '';
int count = 0;
const char* arg = argv[1];
int isError = 0;

if (argc < 2) {
    isError = 1;
}

while (*arg amp; !isError) {     // scan argv[1] for digits
    isError = isdigit(*arg);
    arg  ;
}
arg = argv[1];                // reset arg back to beginning of argv[1]

while (*arg amp;amp; !isError) { 
    if (lastChar == *arg) {
        count  ;
    }
    else {
        if (count > 0) {
            printf("%c%d", lastChar, count);
        }
        lastChar = *arg;
        count = 1;
    }
    arg  ;
}

// print the last character being tracked or error message
if (isError) {
    printf("ERROR");
}
else if (count > 0) {
    printf("%c%d", lastChar, count);
}
printf("n");