В C, как strcmp только первые 2 символа, а затем объединить?

Как в C сделать strcmp только первые 2 символа? Затем объединить с другой строкой? Что-то вроде этого:

char s[10];
scanf("%s",s);

/* if i input "cs332" or "cs234", anything start with cs */

if (strcmp("cs",???)==0)
    strcat(s,"by professor");

person jenifer    schedule 14.05.2011    source источник


Ответы (6)


Вы ищете функцию strncmp, которая функционально идентична strcmp, но ограничивает количество проверяемых символов. Таким образом, вы должны использовать его с длиной два и строкой сравнения "cs". Но у вас есть несколько других проблем здесь.

Во-первых, ваш буфер недостаточно велик. Не существует строки, которая поместилась бы в десятисимвольный буфер, если вы добавите к ней текст «от профессора».

Во-вторых, надежный код никогда не будет использовать scanf со спецификатором формата неограниченной строки: это вызывает проблему переполнения буфера. Семейство scanf предназначено для форматированного ввода, а неформатированного немного больше, чем пользовательский ввод :-)

Если вам нужно надежное решение ввода, см. один моих предыдущих ответов.

В-третьих, вы всегда должны предполагать, что объединение строк может привести к переполнению вашего буфера, и ввести код для предотвращения этого. Вам нужно добавить:

  • текущая длина строки, введенная пользователем.
  • длина добавляемой строки ("по профессору").
  • еще один для нулевого терминатора.

и убедитесь, что буфер достаточно большой.

Метод, который я бы использовал, состоял бы в том, чтобы иметь (например) 200-байтовый буфер, использовать getLine() из связанного ответа (воспроизведенного ниже, чтобы сделать этот ответ автономным) с достаточно меньшим размером (скажем, 100), тогда вы можете быть заверил, что добавление «профессором» не приведет к переполнению буфера.


Функция:

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

#define OK       0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
    int ch, extra;

    // Get line with buffer overrun protection.
    if (prmpt != NULL) {
        printf ("%s", prmpt);
        fflush (stdout);
    }
    if (fgets (buff, sz, stdin) == NULL)
        return NO_INPUT;

    // If it was too long, there'll be no newline. In that case, we flush
    // to end of line so that excess doesn't affect the next call.
    if (buff[strlen(buff)-1] != '\n') {
        extra = 0;
        while (((ch = getchar()) != '\n') && (ch != EOF))
            extra = 1;
        return (extra == 1) ? TOO_LONG : OK;
    }

    // Otherwise remove newline and give string back to caller.
    buff[strlen(buff)-1] = '\0';
    return OK;
}

Тестовый код:

// Test program for getLine().

int main (void) {
    int rc;
    char buff[10];

    rc = getLine ("Enter string> ", buff, sizeof(buff));
    if (rc == NO_INPUT) {
        // Extra NL since my system doesn't output that on EOF.
        printf ("\nNo input\n");
        return 1;
    }

    if (rc == TOO_LONG) {
        printf ("Input too long [%s]\n", buff);
        return 1;
    }

    printf ("OK [%s]\n", buff);

    return 0;
}
person paxdiablo    schedule 14.05.2011

почему бы не сравнивать символы напрямую, а не вызывать strcmp?

E.g.

если(s[0]=='c' && s[1]=='s'){ ... }

person Moses Xu    schedule 14.05.2011

if (strncmp("cs",???, 2)==0) strcat(s,"by professor");

Используйте strncmp

person sehe    schedule 14.05.2011

Несколько способов сделать это.

Сравнение строк:

if ( s[0] == 'c' && s[1] == 's' )

Это наивный способ, так как вы не можете легко расширить его до немного более длинных кодов (скажем, длиной 3/4 символа).

Я думаю, вы поняли, что должны использовать strncmp(), верно?

Конкатенация строк

Не используйте strcat. Действительно. Если вы объедините две строки, длина которых превышает размер s (пункт назначения), у вас возникнут проблемы. Попробуйте вместо этого использовать snprint(), например:

char str[80];
snprintf(str, 80, "%s by professor", s);

Или вы можете использовать strncat(), как указывает Хит:

char s[80];
strncat(s, " by professor", 80);
person Community    schedule 14.05.2011
comment
Почему не strncat()? Намного быстрее, чем snprintf(). - person Heath Hunnicutt; 14.05.2011
comment
@Heath, честно говоря, это сработает. Я думаю, что сначала я добрался до snprintf. - person ; 14.05.2011
comment
Около года назад я написал свой собственный snprintf(). Это было намного проще, чем я себе представлял/опасался. Это было также поучительно. Результат был менее медленным из-за синтаксического анализа строки формата, чем я предполагал до его написания. Я также не поддерживал ничего, кроме ASCII/ANSI, типа K&R sprintf() + n, что делает его snprintf(). Я просто хотел поделиться этим, потому что я призываю людей писать snprintf() для удовольствия. - person Heath Hunnicutt; 14.05.2011

Вы можете использовать strncmp.

Редактировать:

strcat(s,"by professor");

// s is an array of 10 characters. You need to make sure s is big enough  
// to hold the string that needs to be concatenated + to have a terminating 
// character '\0'.
person Mahesh    schedule 14.05.2011

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

#define CS 29539
char s[80];

scanf("%60s", s);
if( *(short *)s == CS )
    if( strlcat(s, " by professor", sizeof(s)) >= sizeof(s) )
        fprintf(stderr, "WARNING: truncation detected: %s", s);
person Mel    schedule 14.05.2011
comment
Нет! Пожалуйста, не пытайтесь повторить это дома, дети. - person Bo Persson; 14.05.2011