How can I read multiple lines from a txt file if I want to store the data in different variables? Each line contain the same data type order: int string string char string, separated with tabs.
For example a line in the txt file look like:
11 \t I would like an apple \t What is your favourite car brand? \t b \t elephant
Thanks for help in advance.
I tried to read it with fscanf(“%d\t%s\t%s\t%c\t%s\n”,..); but I can’t read the strings because %s cut my sentence at the first space and it reads only the first line, I can’t move to the next lines.
This is a
csvfile andscanfwas written to consume this type of data, large files of tabular data. Andscanfis really good at that. Butscanf--- and alsosscanfandfscanf--- skips white space. And white space includes tabs, spaces and newlines.So your file is problematic, by using tab as a separator. Another issue is that many editors translate tabs to spaces up to tab stop columns, so tabs may not be recorded at all. Tabs as symbols are more common on document editors like Word from Microsoft, that can print a symbol for each tab, line break, paragraph mark and so on. On Unix/Linux/Mac
viyou can useset listto seeTABas^I.Example
I will show an example using the 2 alternatives: [1] use
sscanfand [2] parsing the line in code.As usual, it is easier to use encapsulation and pointers and use each record as such: an object of some sort, so it is the way I will use here.
This is the definition used for each record in the example:
In practice this is better:
It is trivial to convert one from another and in the code there are functions included that does it. The main reason to use pointers inside the record is to use just the needed amount of RAM instead of 240 bytes for each and every set of strings.
the file used in the examples
This is almost like in the original example, but I removed the extra spaces. The blank fields at the end has at least one space and this is for testing
scanfconsumption. For the local parser it makes no difference.\tis of course replaced by the delimiter in use.functions in use in the code
These are fairly obvious, but:
so_parsegets a line and returns aRecordwith the extracted fields, by parsing the line.so_parse_scdoes the same, but usessscanfmainfor a testTwo arguments are expected: the file name and the delimiter. The defaults are "input.txt" and
,comma for the delimiter. The delimiter can be entered as ";" or;for a semicolon, "\t" for a TAB, or\nnnfor a decimal value, like\064for@As expected
so_parsegoes ok butso_parse_sccan not parse some lines when TAB is the separator.output using comma as a delimiter
output using TAB as a delimiter
And
scanffailed to read the last record, the one with blank fields since the delimiter is also white space.So why use
scanfThis functions can parse the delimiters and convert types like string,
char,float,doubleandint, in a single call. In generalscanfis capable of processing and converting any validcsvfile. Forvalidwe can try any online validator like this one or read the RFC4180. There is no real formal definition of acsvbecause the format precedes internet and W3C by some time.Here the mask used is
where
xis the delimiter in use. It can parse the strings, thecharand theintvalue. In prodution code:79for a field of80bytes. :)"for example --- see the RFC. Here the fields are not escaped so they can not have a delimiter inside.scanfcan return something from -1 to 5.csvare giant MxN tables of M records with N fields, so all M lines must have N=4 delimiters herex%79[^x]xmeans at most 79 chars notxbetween delimiterx.complete
CCode