#c #arrays #string #strtok #scanf
#c #массивы #строка #strtok #scanf
Вопрос:
Я работаю в программе на C, и у меня есть строка символов с числами, подобная этой:
5 13 12 7 3 0
Я хочу отсканировать ее и поместить каждое из этих целых чисел в массив int. Как мне это сделать?
Это способ использовать sscanf для этого?
Я попробовал следующий код без успеха:
fgets(datatemp, N*3, stdin);
k = 0; garb = 'c';
while(garb != ''){
garb = strtok(datatemp, " ");
array[k] = garb;
k ;
}
ПРИМЕЧАНИЕ: я должен использовать его в функции, которая будет делать то же самое для многих данных, в которых строка ‘datatemp’ будет иметь неизвестное количество целых чисел (и только целых чисел).
Спасибо за любую помощь.
Комментарии:
1. Преобразуйте весь ввод в строку , используя
getline()
, а затем разделите строку символом » «, и у вас будет массив ваших чисел в виде строк. Преобразуйте ваши числа из строки в целое число. Это даст вам желаемый целочисленный массив.2. array[k] = atoi(garb);
3. Почему вы не читаете напрямую из
stdin
intoarray
, покаscanf
не будет успешно4.
int
Ограничено ли количествоN
или это «неизвестное число», такое как 0,1,2,3,…5. В конце я просто сделал то, что сказал @P0W. Но я все еще пытаюсь поступить по-другому, поскольку это может быть полезно в других ситуациях.
Ответ №1:
// Adapted from strtok(3) example.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int
main(int argc, char *argv[])
{
char *str1, *str2, *token, *subtoken;
char *saveptr1,*saveptr2;
int j;
char datatemp[ 120 ];
char delim = ' ';
fgets(datatemp, 119, stdin);
/*
* strtok has to be called with a pointer to the input
* the first time then with a pointer to the string
* subsequently
*/
for(j=1, str1 = datatemp;; j , str1 = NULL)
{
token = strtok_r(str1, amp;delim, amp;saveptr1);
if(token==NULL)
break;
for (str2 = token; ; str2 = NULL)
{
subtoken = strtok_r(str2, amp;delim, amp;saveptr2);
if (subtoken == NULL)
break;
printf(" --> %sn", subtoken);
}
}
exit(0);
}
Комментарии:
1. Спасибо за ваш ответ. Учитывая, что код довольно сложный, для OP, несомненно, было бы полезно, если бы вы могли добавить некоторое объяснение с помощью встроенных комментариев или текста помимо кода.
2. Примечание: нет необходимости вычитать 1, использовать
fgets(datatemp, 120, stdin);
или даже лучшеfgets(datatemp, sizeof datatemp, stdin);
.fgets()
уже учитывает''
.
Ответ №2:
Чтобы использовать fgets()/sscanf()
по запросу OP, см. Ниже.
Использование fgets()/strtol()
обеспечивает лучшую обработку ошибок, чем sscanf()
. Рекомендуем strtol()
Чтобы получить наилучший ответ, OP должен предоставить информацию о том, как данные должны храниться (VLA, malloc, по 1 за раз), проблемы с обработкой ошибок и т. Д.
Трудно сказать, почему операционный код не работал, поскольку дефалькация array[]
отсутствует, но, возможно, он был слишком мал для тестовых данных, и некоторые из них не были изменены по мере необходимости для ввода различных данных.
void foo() {
char buf[100];
if (fgets(buf, sizeof buf, stdin) == NULL) Handle_EOForIOError();
int i = 0;
int n = 0;
int number;
// Count the numbers
while (sscanf(amp;buf[i], "%d %n", amp;number, amp;i) == 1) {
n ;
}
int num[n];
i = 0;
int j;
// scan again, this time save the numbers
while (sscanf(amp;buf[i], "%d %n", amp;num[i], amp;j) == 1) {
i = j;
}
// use the numbers
bar(num, n);
}
Приведенный выше код может использовать, скорее всего, пропустить j
и использовать while (sscanf(amp;buf[i], "%d %n", amp;num[i], amp;i) == 1);
, но мне нужно перепроверить некоторые проблемы с кодовой точкой.
strtol()
лучше, чем sscanf()
. Для использования предложите вспомогательную функцию:
// return non-zero on failure
static int user_strtoi(char **s, int *result) {
char *endptr;
errno = 0;
long num = strtol(*s, amp;endptr, 10);
if (endptr == *s) return 1; // fail as nothing was parsed
if (errno != 0) return 2; // fail due to overflow
if (num < INT_MIN || num > INT_MAX) return 2; // fail due to overflow
*result = (int) num;
*s = endptr;
return 0;
}
Комментарии:
1. array[] — это массив целых чисел, динамически распределяемых с помощью malloc, чтобы соответствовать максимальному размеру чисел, определенных во входном файле. Кроме того, array[] находится внутри вектора структуры, который также выделяется динамически.
2. @user3442466 Предлагает обновить ваш пост, чтобы код включал это важное уточнение. Также опубликуйте более крупный пример выборки данных. 1) Многострочный? 2) В каждой строке одинаковое количество
int
? 3) Учитывая, что вам, похоже, нужен массив «массив целых чисел», должен ли весь «массив целых чисел» быть одинаковой длины? 4) как вы хотите обозначить длинуint
в «массиве целых чисел»? 5) Как вы хотите обозначить длину массива «массива целых чисел»?
Ответ №3:
Вы можете использовать стандартную функцию strtol
, объявленную в заголовке <stdlib.h>
. Например
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main( void )
{
char s[] = "5 13 12 7 3 0";
size_t l = strlen( s );
size_t n = 0;
char *end_ptr = s;
char **next_ptr = amp;end_ptr;
errno = 0;
while ( end_ptr != s l )
{
strtol( *next_ptr, next_ptr, 10 );
if ( errno != 0 ) break;
n;
}
int a[n];
memset( a, 0, n * sizeof( int ) );
end_ptr = s;
size_t i = 0;
while ( end_ptr != s l )
{
int value = ( int )strtol( *next_ptr, next_ptr, 10 );
if ( errno != 0 ) break;
a[i ] = value;
}
for ( i = 0; i < n; i ) printf( "%d ", a[i] );
puts( "" );
return 0;
}
Вывод
5 13 12 7 3 0
Комментарии:
1. Примечание: перед 2-м
while
циклом предложите другойerrno = 0;
. Не уверен в преимуществе проверкиerrno
и не проверки(int)
, теряет ли диапазон. Предлагаю просто использоватьlong
вместоint
.2. @chux в C atoi определяется как (int) strtol(…).:)
3.
atoi()
потеря информации должнаsizeof(long) > sizeof(int)
быть такой(int) strtol()
же. Если код связан сerrno
(переполнением), разумно также беспокоиться о потере данных из-за(int)
приведения. IAC, эти проблемы, вероятно, выходят за рамки основной проблемы OP.4. Это только я, или ваш ввод не соответствует вашему выводу?
0
является ли still и integer правильным?5. @David C. Rankin Это хорошее замечание! Условие должно быть изменено на endptr != s strlen( s)
Ответ №4:
Я предлагаю использовать strtol
в цикле, это быстрее (прямое преобразование без промежуточного буфера), и вы можете проверить наличие ошибок
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char s[128], *p, *q;
int i, n, *v;
/* get user input */
fgets(s, sizeof s, stdin);
/* count integers */
for (p = s, n = 0; ; p = q, n ) {
strtol(p, amp;q, 10);
if (p == q) break;
}
v = malloc(sizeof(int) * n);
/* populate array */
for (p = s, i = 0; i < n; i ) {
v[i] = strtol(p, amp;p, 10);
}
/* print array */
for (i = 0; i < n; i ) {
printf("%dn", v[i]);
}
free(v);
return 0;
}