[英]how to tokenize string to array of int in c?
任何人都知道從每行文本文件中讀取序列號並將其解析為 C 中的數組嗎?
我在文件中的內容:
12 3 45 6 7 8
3 5 6 7
7 0 -1 4 5
我在我的程序中想要什么:
array1[] = {12, 3, 45, 6, 7, 8};
array2[] = {3, 5, 6, 7};
array3[] = {7, 0, -1, 4, 5};
我已經通過多種方式來閱讀它,但唯一的問題是只有當我想每行標記它時。 謝謝你。
下面的代碼將一次讀取一個文件一行
char line[80]
FILE* fp = fopen("data.txt","r");
while(fgets(line,1,fp) != null)
{
// do something
}
fclose(fp);
然后,您可以使用strtok()和sscanf()標記輸入以將文本轉換為數字。
從 sscanf 的 MSDN 頁面:
這些函數 [sscanf 和 swscanf] 中的每一個都返回成功轉換和分配的字段數; 返回值不包括已讀取但未分配的字段。 返回值 0 表示未分配任何字段。 如果出現錯誤或在第一次轉換之前到達字符串末尾,則返回值為 EOF。
以下代碼將字符串轉換為整數數組。 顯然,對於可變長度數組,在實際解析數組之前,您需要一個列表或一些掃描輸入兩次以確定數組的長度。
char tokenstring[] = "12 23 3 4 5";
char seps[] = " ";
char* token;
int var;
int input[5];
int i = 0;
token = strtok (tokenstring, seps);
while (token != NULL)
{
sscanf (token, "%d", &var);
input[i++] = var;
token = strtok (NULL, seps);
}
推桿:
char seps[] = " ,\t\n";
將使輸入更加靈活。
我不得不進行搜索以提醒自己語法 - 我在 MSDN 中找到了它
我要做的是創建一個這樣的函數:
size_t read_em(FILE *f, int **a);
在函數中,為指針*a
分配一些內存,然后開始從f
讀取數字並將它們存儲在*a
。 當您遇到換行符時,只需返回您存儲在*a
的元素數。 然后,像這樣調用它:
int *a = NULL;
FILE *f = fopen("Somefile.txt", "r");
size_t len = read_em(f, &a);
// now a is an array, and len is the number of elements in that array
有用的功能:
以下代碼可能正是您要找的。 希望您在評論中不需要太多描述,但是,如果您有任何疑問,請隨時提出。
它基本上使用fgets
循環讀取每一行,並使用strtok
將該行分隔為字段。 它構造了一個包含實際數據的整數數組的鏈表 - 您可以在最后轉儲表的代碼中看到該鏈表的使用。
它還有一種方法可以處理輸入文件中任意大小的行而不會出現緩沖區溢出(當然受內存限制)。 請記住, strtok
只需要一行中的每個字段之間有一個空格,盡管可以重新編碼以處理多個空格甚至任何數量的空格。 我一直保持簡單,因為代碼已經變得有點大了:-)
atoi
函數用於將每行上的單個單詞轉換為整數。 如果您想對這些進行錯誤檢查,我會調用您自己的變體,它還會檢查單詞中的所有字符是否都是數字。
使用您的輸入文件:
12 3 45 6 7 8
3 5 6 7
7 0 -1 4 5
它產生以下方面的輸出:
0x97b5170, size = 6:
12 3 45 6 7 8
0x97b51d0, size = 4:
3 5 6 7
0x97b51e0, size = 5:
7 0 -1 4 5
這是產生該輸出的代碼:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
// This is the linked list of integer arrays.
typedef struct _tIntArray {
int size;
int *array;
struct _tIntArray *next;
} tIntArray;
static tIntArray *first = NULL;
static tIntArray *last = NULL;
// Add a line of integers as a node.
static int addNode (char *str) {
tIntArray *curr; // pointers for new integer array.
char *word; // word within string.
char *tmpStr; // temp copy of buffer.
int fldCnt; // field count for line.
int i;
// Count number of fields.
if ((tmpStr = strdup (str)) == NULL) {
printf ("Cannot allocate duplicate string (%d).\n", errno);
return 1;
}
fldCnt = 0;
for (word = strtok (tmpStr, " "); word; word = strtok (NULL, " "))
fldCnt++;
free (tmpStr);
// Create new linked list node.
if ((curr = malloc (sizeof (tIntArray))) == NULL) {
printf ("Cannot allocate integer array node (%d).\n", errno);
return 1;
}
curr->size = fldCnt;
if ((curr->array = malloc (fldCnt * sizeof (int))) == NULL) {
printf ("Cannot allocate integer array (%d).\n", errno);
free (curr);
return 1;
}
curr->next = NULL;
for (i = 0, word = strtok (str, " "); word; word = strtok (NULL, " "))
curr->array[i++] = atoi (word);
if (last == NULL)
first = last = curr;
else {
last->next = curr;
last = curr;
}
return 0;
}
int main(void) {
int lineSz; // current line size.
char *buff; // buffer to hold line.
FILE *fin; // input file handle.
long offset; // offset for re-allocating line buffer.
tIntArray *curr; // pointers for new integer array.
int i;
// Open file.
if ((fin = fopen ("qq.in", "r")) == NULL) {
printf ("Cannot open qq.in, errno = %d\n", errno);
return 1;
}
// Allocate initial line.
lineSz = 2;
if ((buff = malloc (lineSz+1)) == NULL) {
printf ("Cannot allocate initial memory, errno = %d.\n", errno);
return 1;
}
// Loop forever.
while (1) {
// Save offset in case we need to re-read.
offset = ftell (fin);
// Get line, exit if end of file.
if (fgets (buff, lineSz, fin) == NULL)
break;
// If no newline, assume buffer wasn't big enough.
if (buff[strlen(buff)-1] != '\n') {
// Get bigger buffer and seek back to line start and retry.
free (buff);
lineSz += 3;
if ((buff = malloc (lineSz+1)) == NULL) {
printf ("Cannot allocate extra memory, errno = %d.\n", errno);
return 1;
}
if (fseek (fin, offset, SEEK_SET) != 0) {
printf ("Cannot seek, errno = %d.\n", errno);
return 1;
}
continue;
}
// Remove newline and process.
buff[strlen(buff)-1] = '\0';
if (addNode (buff) != 0)
return 1;
}
// Dump table for debugging.
for (curr = first; curr != NULL; curr = curr->next) {
printf ("%p, size = %d:\n ", curr, curr->size);
for (i = 0; i < curr->size; i++)
printf (" %d", curr->array[i]);
printf ("\n");
}
// Free resources and exit.
free (buff);
fclose (fin);
return 0;
}
您的文件是否有特定數量的行,或者您是否需要能夠將任意數字讀入隨機數組?
這是逐行讀取文件的代碼。
#include <stdio.h>
int main()
{
char *inname = "test.txt";
FILE *infile;
char line_buffer[BUFSIZ];
infile = fopen(inname, "r");
if (!infile) {
printf("Couldn't open file %s for reading.\n", inname);
return 0;
}
while (fgets(line_buffer, sizeof(line_buffer), infile)) {
// process line
}
return 0;
}
您可以使用sscanf
或許多標記/轉換函數中的任何一個來提取數字。 BUFSIZ
是來自stdio.h
一個很好的常量,旨在使流 I/O 在目標系統上高效。
使用strtol()
解析每一行:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
static char buffer[1024];
static long values[256];
while(fgets(buffer, sizeof buffer, stdin))
{
char *current = buffer;
size_t i = 0;
while(*current && *current != '\n' &&
i < sizeof values / sizeof *values)
{
char *tail = NULL;
errno = 0;
values[i] = strtol(current, &tail, 0);
if(errno || tail == current)
{
fprintf(stderr, "failed to parse %s\n", current);
break;
}
++i, current = tail;
}
// process values
printf("read %i values\n", i);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.