Re: reading in multiple strings with scanf
- From: user923005 <dcorbit@xxxxxxxxx>
- Date: Wed, 3 Dec 2008 12:36:16 -0800 (PST)
On Dec 3, 7:13 am, Heiko Schepanski <deutron...@xxxxxx> wrote:
nick_keighley_nos...@xxxxxxxxxxx wrote:
On 3 Dec, 12:23, Heiko Schepanski <deutron...@xxxxxx> wrote:
No matter what I input into the console, scanf returns 1 but it should
be able to read all 6 fields in correctly. What am I doing wrong?
please give an example of your input
struct _bauelement
{
char kennnummer[9+1];
char bezeichnung[30+1];
char einheit[10+1];
double wert;
char toleranzklasse;
char bemerkungen[120+1];
} be;
int num = scanf("%s, %s, %s, %lf, %c, %s",
be.kennnummer, sizeof(be.kennnummer),
be.bezeichnung, sizeof(be.bezeichnung),
be.einheit, sizeof(be.einheit),
&be.wert,
&be.toleranzklasse,
be.bemerkungen, sizeof(be.bemerkungen));
in addition to viza's comments scanf() doesn't accept the sizeof
arguments you have in your call. If it read a second string it
would try to store it in sizeof(be.kennnummer) which I'd expect
to give a segmentation error. Re-read your documentation for scanf().
I suspect you need to use fgets() the parse the string "by hand".
Consider strtok().
--
Nick Keighley
Testing can show the presense of bugs, but not their absence.
-- Dijkstra
It's me again :-)
Since I have multiple times in my app a call to printf, sprintf, scanf,
and fscanf with always the same arguments (see my other posts) I came up
with an absolutely sick idea. Because I need *all* values from my struct
and I use it in the same order they appear in the struct I tried:
printf("%9s, %30s, %10s, %.2lf, %i, %s\n", be); // be is the struct var
Sadly to say, it didn't work and threw an exception :-(
Maybe something like this:
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
char *getsafe(char *buffer, int count)
{
char *result = buffer,
*np;
if ((buffer == NULL) || (count < 1))
result = NULL;
else if (count == 1)
*result = '\0';
else if ((result = fgets(buffer, count, stdin)) != NULL)
if (np = strchr(buffer, '\n'))
*np = '\0';
return result;
}
/* The default delimiters are chosen as some ordinary white space
characters: */
static const char default_delimiters[] =
{' ', '\n', '\t', '\r', '\f', 0};
/*
* The tokenize() function is similar to a reentrant version of strtok
().
* It parses tokens from 's', where tokens are substrings separated by
* characters from 'delimiter_list'.
* To get the first token from 's', tokenize() is called with 's' as
its first
* parameter.
* Remaining tokens from 's' are obtained by calling tokenize() with
NULL for
* the first parameter.
* The s of delimiters, identified by 'delimiter_list', can change
from call
* to call.
* If the list of delimiters is NULL, then the standard list
'default_delimiters'
* (see above) is used.
* tokenize() modifies the memory pointed to by 's', because it writes
null
* characters into the buffer.
*/
char *tokenize(char *s, const char *delimiter_list, char
**placeholder)
{
if (delimiter_list == NULL)
delimiter_list = default_delimiters;
if (delimiter_list[0] == 0)
delimiter_list = default_delimiters;
if (s == NULL)
s = *placeholder;
if (s == NULL)
return NULL;
/*
* The strspn() function computes the length of the initial segment of
the first
* string that consists entirely of characters contained in the second
string.
*/
s += strspn(s, delimiter_list);
if (!s[0]) {
*placeholder = s;
return NULL;
} else {
char *token;
token = s;
/*
* The strpbrk() function finds the first occurrence of any character
contained in
* the second string found in the first string.
*/
s = strpbrk(token, delimiter_list);
if (s == NULL)
*placeholder = token + strlen(token);
else {
*s++ = 0;
*placeholder = s;
}
return token;
}
}
#ifdef UNIT_TEST
static char whitespace[UCHAR_MAX + 1];
/*
This test will create token separators as any whitespace or any
punctuation
marks:
*/
void init_whitespace()
{
int i;
int index = 0;
for (i = 0; i < UCHAR_MAX; i++) {
if (isspace(i)) {
whitespace[index++] = (char) i;
}
if (ispunct(i)) {
whitespace[index++] = (char) i;
}
}
}
static struct bauelement {
char kennnummer[9 + 1];
char bezeichnung[30 + 1];
char einheit[10 + 1];
double wert;
char toleranzklasse;
char bemerkungen[120 + 1];
} be;
char *strstart(char *s)
{
while (isspace(*s))
s++;
return s;
}
void get_be(char *ts, char *white, struct bauelement * be)
{
char *p = NULL;
char *token;
int iteration = 0;
token = tokenize(ts, white, &p);
while (token) {
switch (iteration++) {
case 0:
strncpy(be->kennnummer, strstart(token), sizeof be-
kennnummer);break;
case 1:
strncpy(be->bezeichnung, strstart(token), sizeof be-
bezeichnung);break;
case 2:
strncpy(be->einheit, strstart(token), sizeof be->einheit);
break;
case 3:
be->wert = atof(strstart(token));
break;
case 4:
be->toleranzklasse = *strstart(token);
break;
case 5:
strncpy(be->bemerkungen, strstart(token), sizeof be-
bemerkungen);break;
}
token = tokenize(NULL, white, &p);
}
}
static char str[256] = "1234, Plate, cm, 14.99, 60, Part is OK";
int main(void)
{
char yourstring[256];
char ws[2] = ",";
get_be(str, ws, &be);
printf("%s, %s, %s, %g, %d, %s.\n", be.kennnummer, be.bezeichnung,
be.einheit, be.wert, be.toleranzklasse, be.bemerkungen);
puts("You give me one:");
fflush(stdout);
getsafe(yourstring, sizeof yourstring);
get_be(yourstring, ws, &be);
printf("%s, %s, %s, %g, %d, %s.\n", be.kennnummer, be.bezeichnung,
be.einheit, be.wert, be.toleranzklasse, be.bemerkungen);
return 0;
}
/* Some possible output:
1234, Plate, cm, 14.99, 54, Part is OK.
You give me one:
1212, Silverware, inches, 12, 32, What is not
1212, Silverware, inches, 12, 51, What is not.
*/
#endif
.
- Follow-Ups:
- Re: reading in multiple strings with scanf
- From: Heiko Schepanski
- Re: reading in multiple strings with scanf
- References:
- reading in multiple strings with scanf
- From: Heiko Schepanski
- Re: reading in multiple strings with scanf
- From: nick_keighley_nospam
- Re: reading in multiple strings with scanf
- From: Heiko Schepanski
- reading in multiple strings with scanf
- Prev by Date: Re: Question regarding prototypes for 0-ary functions.
- Next by Date: Re: volatile Keyword Question
- Previous by thread: Re: reading in multiple strings with scanf
- Next by thread: Re: reading in multiple strings with scanf
- Index(es):
Relevant Pages
|