скопировать строку из одного места в другое - PullRequest
1 голос
/ 19 мая 2010

копировать строку между запятыми

ввод

(aaa),(ddD),(sss),(ppp)

p=malloc(sizeof(char)*200);
gets(p);

я хочу удерживать ввод

p[0]="(aaa)"
p[1]="(ddD)"
p[2]="(sss)"
p[3]="(ppp)"

Ответы [ 3 ]

4 голосов
/ 19 мая 2010

Возможно, вам придется использовать strtok .

Вот полное решение всех ваших проблем:

// tokens.c

#include <stdio.h>
#include <string.h> /* for strtok, strlen and strcpy. */
#include <stdlib.h> /* for malloc, realloc and free. */ 

static char **tokens = NULL; /* Dynamic array of string tokens. */
static int token_count = 0; /* Number of tokens added. */

/* Grows the `tokens' array as needed and appends `tok' to it. */
static void
copy_token (char *tok)
{
  if (token_count == 0)
    tokens = malloc (sizeof (char*));
  else
    tokens = realloc (tokens, sizeof (char*) * (token_count + 1));
  tokens[token_count] = malloc (strlen (tok) + 1);
  strcpy (tokens[token_count], tok);
  ++token_count;
}

/* Extracts tokens from `s' and calls copy_token to add it to `tokens'. */
static void
tokenize_by_comma (char *s)
{
  char *tok = strtok (s, ",");
  while (tok != NULL)
    {      
      copy_token (tok);
      tok = strtok (NULL, ",");
    }  
}

/* If you run copy_after, the total length of all tokens 
   must not exceed BUFF_SIZE. */
#define BUFF_SIZE 1024 
static char s_copy[BUFF_SIZE + 1];

/* Makes a string of all the tokens by moving `s' next to `after'. */
static char *
copy_after (const char *s, const char *after)
{
  int i;
  int appended = 0;
  strcpy (s_copy, "");
  for (i = 0; i < token_count; ++i)
    {
      int is_s = (strcmp (tokens[i], s) == 0);
      int is_after = (strcmp (tokens[i], after) == 0);
      if (is_after)
        {
          strcat (s_copy, after);
          strcat (s_copy, ",");
          strcat (s_copy, s);
          appended = 1;
        }
      else if (!is_s)
        {
          strcat (s_copy, tokens[i]);
          appended = 1;
        }
      if (i != (token_count - 1) && appended) 
        strcat (s_copy, ",");
      appended = 0;
    }
  return s_copy;
}

/* Prints the `tokens'. */
static void 
print_tokens ()
{
  int i;
  for (i = 0; i < token_count; ++i)
    printf ("%s\n", tokens[i]);
}

/* Frees the memory allocated for `tokens'. */
static void 
free_tokens ()
{
  int i;
  for (i = 0; i < token_count; ++i)
    free (tokens[i]);
  free (tokens);
  token_count = 0;
  tokens = NULL;
}

/* Test. Pass the tokens as a single command line argument. */
int
main (int argc, char **argv)
{
  tokenize_by_comma (argv[1]);
  print_tokens ();
  if (argc == 4)
    {
      printf ("%s\n", copy_after (argv[2], argv[3]));
    }
  free_tokens ();
  return 0;
}

Тестовый прогон:

$ ./tokens "(aaa),(ddD),(sss),(ppp)"
(aaa)
(ddD)
(sss)
(ppp)
$ ./tokens "(aaa),(ddD),(sss),(ppp)" "(ddD)" "(ppp)"
(aaa)
(ddD)
(sss)
(ppp)
(aaa),(sss),(ppp),(ddD)
1 голос
/ 19 мая 2010

Избегайте использования gets(3), это приведет к некоторым интересным проблемам даже в первые дни Интернета из-за легкого переполнения буфера . Вместо этого используйте fgets(3).

0 голосов
/ 19 мая 2010

Если вы уверены, что у вас всегда будет четыре входа, вы можете использовать что-то вроде:

scanf("%[^,],%[^,],%[^,],%[^,]", p[0], p[1], p[2], p[3]);

если вы не знаете количество входов, вы, вероятно, вместо этого выполняете чтение в цикле:

for (i=0; i<limit; i++)
    if (!scanf("%[^,],", p[i]))
        break;
if (i<limit)
    scanf("%[^\n]", p[i]);

или, если хотите, вы можете написать цикл следующим образом:

for (i=0; i<limit && scanf("%[^,],", p[i]); i++)
    ;

В любом случае, это считывает данные, которые не содержат запятую, за которой следует запятая (то есть чтение, чтобы проверить ее наличие), пока не произойдет сбой. Предполагая, что данные в правильном формате, произойдет сбой, если есть данные без запятой. Затем мы делаем еще одно чтение после цикла, чтобы прочитать остаток строки в последнем элементе.

Обратите внимание, что если ваши данные также могут содержать запятую, что-то вроде:

(ааа, ГЭБ), (ссс, ддд)

где первый элемент данных должен быть "(aaa, bbb)", а второй "(ccc, ddd)", это будет не работать - для чего-то подобного вы можете переписать преобразование для отдельного ввода что-то вроде: «% [^)])» для чтения до закрывающей скобки, за которой следуют скобки и запятая.

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