#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
withstrcpy()
.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");