Hello I'm trying to search a txt file in C.
sscanf(line, "%s %[^|]| %[^|]| %[^|]|", temp->phoneNumber, temp->code, temp->name, temp->address); //scan all the information from each line
` This code here scans the line and stores each part in a temporary variable. Records are in this format:
1-999-213-1301 x3326|Matthew Hamilton|434 Gerhold Isle, New York, AZ 031-3012|true
Keep note of "x3326"
. That is a code that each address has. However some records in the file like this one below doesn't have that code. Now when searching using the phone number the program scans that line and realises there is no code thus it returns a failure.
(649) 169-9928|Olson, Olson and Olson|Apt. 654 7030 Nienow Landing, Lake Evieshire, WI 85916|false
What can I do to fix this problem?
CodePudding user response:
Try removing the spaces in the pattern: "%s%[^|]|%[^|]|%[^|]|"
CodePudding user response:
Does each code
start with an 'x'
? In that case I would first try to scan phonenumber
until either 'x'
or '|'
is reached. If 'x'
is reached everything up to next '|'
should be code
. On the other hand, if '|'
is reached, then code
should scan the empty string.
int inc=0; /* Used to keep track of characters scanned */
sscanf(line, " %[^x|]%[^|]|%n", temp->phonenumber, temp->code, &inc);
/* `inc` will only be set if `%n` is reached while scanning */
if (!inc)
{
/* Handle parse errors */
}
/* scan rest of line */
const char *l = line inc;
/*
reset inc to zero, so we can use it to detect if next
scan is sucessfull */
*/
inc = 0;
sscanf(l, " %[^|]| %[^|]|%n", temp->name, temp->address, &inc);
if (!inc)
{
/* Handle parse errors */
}
l =inc;
inc=0
/* Continue parsing rest of line */
If there is no code
, that field should now contain a zero-length string.
NOTE 1: Trailing whitespace in the fields will be copied into the destination buffers. Removing those is left as an exercise for the reader.
NOTE 2: NEVER EVER USE %s
OR %[
CONVERSIONS WITHOUT A FIELD WIDTH MODIFIER !!
NOTE 3: Personally, I wouldn't use any scanf
function for this, but since the question is about sscanf
, there is sscanf
in the answer
CodePudding user response:
"%s"
cannot scan in "1-###-###-#### x3326"
nor "(###) ###-####"
as both have spaces in them which stops "%s"
scanning.
OP appears to only want to match the phone number and note, sscanf()
is not needed.
Find the offset of the first '|'
;
size_t offset = strcspn(line, "|");
Compare with strncmp()
if (strncmp(line, target_phone_number, offset) == 0 && target_phone_number[offset] == 0) {
; // Match!
}
It is that easy.
CodePudding user response:
To extract the phone number from a line, strspn
and strcspn
can be used.
#include <stdio.h>
#include <string.h>
int main ( void) {
// char *check = "1-999-888-7777 x6543|xxxxxx|########|true";
char *check = "(888) 222-3333|mmmmmmmm|@@@@@@|false";
char phone[50] = "1-";
size_t span = 0;
check = strcspn ( check, "(-"); // find first ( or -
check = ( '(' == *check || '-' == *check); // advance one character
if ( 3 == ( span = strspn ( check, "0123456789"))) { // count digits
strncat ( phone, check, span);
strcat ( phone, "-");
check = span; // advance past first set of digits
check = strcspn ( check, "0123456789"); // find next digit
if ( 3 == ( span = strspn ( check, "0123456789"))) { // count digits
strncat ( phone, check, span);
strcat ( phone, "-");
check = span; // advance past digits
check = strcspn ( check, "0123456789"); // find next digit
if ( 4 == ( span = strspn ( check, "0123456789"))) { // count digits
strncat ( phone, check, span);
check = span; // advance past digits
if ( ( span = strcspn ( check, "|"))) { // count to |
if ( span 1 < sizeof phone - strlen ( phone)) {
strncat ( phone, check, span);
}
}
printf ( "%s\n", phone);
}
}
}
return 0;
}
For the two formats, this builds a phone string of
1-999-888-7777 x6543
1-888-222-3333
Read each line from the file with fgets
, build the phone string and compare to the phone number you are looking for.
strstr
can be used to see if the desired phone number is in the phone string. For example strstr ( phone, "222-3333")
would match the phone string 1-888-222-3333
.