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

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

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

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;
}

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

3 ответа

Решение

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

  • Как уже упоминал кто-то в комментарии, вам нужен буфер размером 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 с просто цифры. Таким образом, вы можете создать массив из 256 элементов (есть 256 различных char s) все изначально установлено на 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 ссылается на указатель pos чтобы получить текущий символ, который затем интерпретируется как unsigned char потому что массивы не могут иметь отрицательные показатели. Эта позиция затем смотрит в counters массив и оценивается в if заявление. Наконец, значение увеличивается (но только после сравнения) с помощью оператора постинкремента.

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

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

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

в

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

Пожалуйста, обновите другие строки.

Пытаться:

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

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;
}

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

Другие вопросы по тегам