Объединение двух строк в одну строку, которая исключает одни и те же буквы в C

Привет, я так новичок в программировании и хочу узнать некоторые из вас 🙂 Я делаю программу в .c, и я застрял в части. Я хочу получить 3 или более входных макс. 5 символов. (Например: HELLO, HI, GOOD, BYE) И я хочу уложить их в новую строку, которая имеет одни и те же буквы только один раз из этих 4 строк (пример: H, E, L, L, O, I, G, D ,ОТ)

#include  #include  int main(void) { char first[5], second[5], third[5], fourth[5]; printf("Enter 1st word: \n"); scanf(" %5s", &first); printf("Enter 2nd word: \n"); scanf(" %5s", &second); printf("Enter 3rd word: \n"); scanf(" %5s", &third); printf("Enter 4th word: \n"); scanf(" %5s", &fourth); char stack[21]; // i want a new string like this and then combine first 4 strings // in this string... return 0; } 

Надеюсь, вы можете сообщить мне, каким образом я могу это сделать. (Я тоже новичок на сайте. Я искал это, но не смог найти. Извините, если он существует.)

Сначала некоторые комментарии к вашему коду:

  • Как уже упоминалось в комментарии, вам нужен буфер размером n + 1 для хранения n символьной строки. Это связано с тем, что в C длина строки нигде не сохраняется. Вместо этого к строке, которая отмечает ее конец, добавляется специальный байт NUL. Поэтому ваши first , …, fourth массивы должны иметь длину не менее 6.
  • Что делать, если худший случай случается, и пользователь вводит четыре непересекающихся слова, каждая из которых стоит 5 символов? Тогда ваша комбинированная строка будет насчитывать 20 символов. Таким образом, ваш массив stack должен иметь возможность разместить 21 символ (снова 1 для завершающего байта NUL). (Также упоминается комментарий пользователя3121023.)
  • Чтобы прочитать строку с помощью scanf , передайте аргумент типа char * , а не char (*)[6] . first уже распадается на char * поэтому дополнительно не берете его адрес (как в &first ). Включите предупреждения своего компилятора (используйте, по крайней мере, -Wall ), чтобы получить информацию об этих ошибках. (Также упоминается Dere0405, когда я печатал этот ответ.)
  • Ваше использование scanf небезопасно. Если пользователь вводит строку длиной более 5 символов, вы будете читать за ее пределами. Вы можете изменить спецификатор формата, чтобы прочитать %5s чтобы сказать scanf прекратить чтение после 5-го символа. Однако это оставит лишние символы в конце строки. Лучшим вариантом было бы использовать fgets или getline для чтения всей строки ввода. В качестве альтернативы просто передайте строки как аргументы командной строки (мое предпочтительное решение).

Теперь к реальной проблеме:

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

Вам нужно будет перебрать все пять строк и проверить каждый символ, если он уже был добавлен в stack . Если это так, продолжайте, иначе добавьте его в stack . Чтобы перебрать строку, мы можем использовать следующую идиому.

 int i; for (i = 0; first[i]; ++i) printf("The character at position %d is '%c'\n", i, first[i]); 

В качестве альтернативы, если нам не нужно ссылаться на текущий индекс, следующая идиома более компактна.

 char * pos; for (pos = first; *pos; ++pos) printf("The current character is '%c'\n", *pos); 

Обратите внимание на то, как мы используем тот факт, что first – строка C – заканчивается байтом NUL, который оценивается как false. В противном случае мы не знали бы, где остановить итерацию.

Теперь, когда мы знаем, как перебирать символы строки, как мы можем проверить, был ли уже добавлен символ? Приходят два решения:

  1. Переверните stack и сравните каждый элемент с текущим символом. Хотя для ваших коротких строк это может быть метод выбора, он будет расти неэффективно для более длинных строк.

  2. Создайте счетчик для каждого символа и увеличивайте его при каждом добавлении в stack . Вы можете использовать тот факт, что char s – это просто цифры. Таким образом, вы можете создать массив с 256 элементами (имеется 256 различных char ), все из которых первоначально установлены в 0, а затем увеличивают позицию для добавляемого символа. Например:

     int counters[256]; memset(counters, 0, sizeof(counters)); /* fill with 0s */ 

    А потом в вашем коде:

     if (counters[(unsigned char) (*pos)]++) { /* Character was already added. Do nothing. */ } else { /* Character was not added yet. Add it to stack. */ } 

    Значение if (counters[(unsigned char) (*pos)]++) немного сложнее. Во-первых, *pos dreferences указатель pos чтобы получить текущий символ, который затем интерпретируется как unsigned char потому что массивы не могут иметь отрицательные индексы. Затем эту позицию просматривают в массиве counters и оценивают в выражении if . Наконец, значение увеличивается (но только после сравнения) с помощью оператора post-increment.

Не забудьте завершить stack с байтом NUL в конце.

Обновите свой код следующим образом:

 printf("Enter 1st word: \n"); scanf(" %s", &first); 

в

 printf("Enter 1st word: \n"); scanf(" %s", first); 

Обновите другие строки.

Пытаться:

 #include  #include  int main(void) { char strings[4][6]; printf("Enter 1st word: \n"); scanf(" %s", strings[0]); printf("Enter 2nd word: \n"); scanf(" %s", strings[1]); printf("Enter 3rd word: \n"); scanf(" %s", strings[2]); printf("Enter 4th word: \n"); scanf(" %s", strings[3]); char stack[21]; // This needs to be pretty much bigger than all combined just in case // Initialize the stack string to 0 length stack[0] = '\0' // Move through each word for(unsigned char word = 0; word < 4; word++){ // Move through each letter of each word for(unsigned char letter = 0; letter < strlen(strings[word]); letter++){ // Test to see if the current letter is within the current stack string unsigned char schar; for(schar = 0; schar < strlen(stack); schar++){ if(stack[schar] == strings[word][letter]) break; } if(schar >= strlen(stack)){ unsigned char sstacklen = strlen(stack); stack[sstacklen] = strings[word][letter]; stack[sstacklen+1] = '\0'; } } } return 0; } 

Это должно работать на то, что вы хотите, это была быстрая запись, поэтому могут быть небольшие ошибки!