Объединить два конкретных столбца из строки на языке Си - PullRequest
0 голосов
/ 13 июня 2018

Я хочу объединить два конкретных столбца из строки на языке C.Линия похожа на "Привет, мир, привет!"Он состоит из нескольких слов и пробела.Ниже мой код.В этой функции c1 и c2 представляют номер столбца, а ключ массива представляет собой объединенную строку.Но бегать нехорошо.

char *LinetoKey(char *line, int c1, int c2, char key[COLSIZE]){
    char *col2 = (char *)malloc(sizeof(char));
    while (*line != '\0' && isspace(*line) )
        line++;
    while(*line != '\0' && c1 != 0){
        if(isspace(*line)){
            while(*line != '\0' && isspace(*line))
                line++;
            c1--;
            c2--;
        }else
            line++;
    }
    while (*line != '\0' && *line != '\n' && (isspace(*line)==0))
        *key++ = *line++;
    *key = '\0';
    while(*line != '\0' && c2 != 0){
        if(isspace(*line)){
            while(*line != '\0' && isspace(*line))
                line++;
            c2--;
        }else
            line++;
    }
    while (*line != '\0' && *line != '\n' && isspace(*line)==0)
        *col2++ = *line++;
    *col2 = '\0';
    strcat(key,col2);
    return key;
}

Ответы [ 2 ]

0 голосов
/ 14 июня 2018

Непонятно, что вы пытаетесь сделать.Если Дэвид Коллинз предложил то, что вы ищете - объединение слов по индексу слов - вот отправная точка ( demo ):

  • Ваша функция должна минимизироватьколичество обходов строк .Чтобы помочь этому, приведенный ниже код использует char** вместо char* (своего рода "потоки символов").
  • Функция должна иметь возможность подсчитывать количество символов, которое будет иметь результат до фактической конкатенации, чтобы можно было выделить строку назначения в свободном хранилище.Если catwords вызывается с нулевым адресатом, он учитывает только длину строки результата.

Что касается фактической реализации, вам придется пройти строку слово за словом и решить, следует ли копировать или пропустить слово.См. Код ниже для следующих функций:

  • nextword - пропускает пробелы до тех пор, пока не найдет символ, не являющийся пробелами.
  • copyword - копирует текущийслово, если пункт назначения действителен, или пропускает его, если нет.Возвращает количество скопированных / пропущенных символов.


#include <ctype.h>
#include <stdlib.h>

void nextword( const char** ps )
{
  while ( **ps && isspace( **ps ) )
    ++*ps;
}

int copyword( char** const pd, const char** ps )
{
  // remember the starting point
  const char* b = *ps;

  // actual copy
  if ( pd && *pd ) while ( **ps && !isspace( **ps ) )
    *( *pd )++ = *( *ps )++;

  // skip the word (no destination)
  else while ( **ps && !isspace( **ps ) )
    ( *ps )++;

  // return the length
  return *ps - b;
}

int catwords( char* d, const char* s, const int* c )
{
  int len = 0;
  int iw = 0;
  int ic = 0;
  const char** ps = &s;
  char** pd = &d;

  for ( nextword( ps ); **ps && c[ ic ] > -1; nextword( ps ), ++iw )
    if ( iw == c[ ic ] )
    {
      len += copyword( pd, ps );
      ++ic;
    }
    else
    {
      copyword( 0, ps ); // just skip the current word
    }

  if ( d )
    **pd = '\0';

  return len;
}

int main()
{
  // static buffer test
  {
    char d[ 1024 ];
    int t[] = { 0, 3, -1 };
    catwords( d, "Hello world. Hello world!", t );
    puts( d );
  }

  // dynamic buffer test
  {
    const char* s = "The greatness of a man is not in how much wealth he acquires, but in his integrity and his ability to affect those around him positively.";
    int t[] = { 1, 5, 16, -1 };
    int dstcharcount = catwords( 0, s, t ) + 1;
    char* d = (char*)malloc( dstcharcount * sizeof( char ) );
    catwords( d, s, t );
    puts( d );
    free( d );
  }

  return 0;
}
0 голосов
/ 13 июня 2018

Вот возможное решение с использованием strtok().Он может обрабатывать произвольное количество столбцов (при необходимости увеличьте размер buf) и будет работать, если порядок столбцов будет изменен на обратный (т. Е. c1> c2).Функция возвращает 1 в случае успеха (токены успешно объединены), 0 в противном случае.

Обратите внимание, что strtok() изменяет свой аргумент - поэтому я скопировал input во временный буфер char buf[64].

/*
 * Merge space-separated 'tokens' in a string.
 * Columns are zero-indexed.
 *
 * Return: 1 on success, 0 on failure
 */
int merge_cols(char *input, int c1, int c2, char *dest) {
    char buf[64];
    int col = 0;
    char *tok = NULL, *first = NULL, *second = NULL, *tmp = NULL;

    if (c1 == c2) {
        fprintf(stderr, "Columns can not be the same !");
        return 0;
    }

    if (strlen(input) > sizeof(buf) - 1) return 0;

    /*
     * strtok() is _destructive_, so copy the input to
     * a buffer.
     */
    strcpy(buf, input);

    tok = strtok(buf, " ");
    while (tok) {
        if (col == c1 || col == c2) {
            if (!first)
                first = tok;
            else if (first && !second)
                second = tok;
        }
        if (first && second) break;
        tok = strtok(NULL, " ");
        col++;
    }
    // In case order of columns is swapped ...
    if (c1 > c2) {
        tmp = second;
        second = first;
        first = tmp;
    }
    if (first) strcpy(dest, first);
    if (second) strcat(dest, second);

    return first && second;
}

Пример использования:

char *input = "one two three four five six seven eight";
char dest[128];

// The columns can be reversed ...
int merged = merge_cols(input, 7, 1, dest);
if (merged)
    puts(dest);

Также обратите внимание, что при использовании strtok() очень легко использовать разные разделители - так что если вы хотите использовать разделенные запятыми или табуляциейввод вместо пробелов, вы просто меняете второй аргумент при его вызове.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...