How to print out a specific numeric pattern - c

I just had a question about C. I have a file that has text in the format of:
7034327874
5408438437
3267239807
1824566789
I was wondering how I would read in the data and in another file, print out:
703-432-7874
540-843-8437
326-723-9807
182-456-6789

Just consider these numbers as strings of characters (each character happens to be a digit). Then do character processing on them.
For example:
char str[16];
memset (str, 0, sizeof(str));
if (scanf(" %15[0-9]", &str) > 0)
printf("%.3s", str);
should, if fed with 0734327574, output 073 (notice that your example don't explain what should have happened in that case, and I am guessing one way of doing it. My guess could be wrong if 0734327574 is actually meant as an octal number for the decimal number 124891004).
The rest is an exercise to the reader. Of course you need to carefully read the documentation of memset, of scanf, of printf. Don't forget to end printf format strings with \n or to call fflush on stdout (which is often line-buffered).
Remember that numbers don't have digits. Only their notation have digits. The number 20, written in Roman notation XX, in English twenty, in French vingt, in hexadecimal 0x14, in octal 024 (or even 248), in binary 10100, as the simple arithmetic expression 3*7-1, is still the same number (which happens to be twice the number of fingers I have on my hands, and is also the number of arrondissements in Paris).

Related

Store leading zeroes in C

For starters, I'm new to programming
I'd like to know how to store a number with leading zeroes in it with scanf instead of modifying the printf. Is it related to data types? If so, what is it? and how do I use it? I currently only know int, double and float
For example, I'd like to input the number "02" and receive "02" as the output, and when I input "2" the output will also be "2".
how to store a number with leading zeroes (?)
I currently only know int, double and float
To store an integer and the leading zero count is then 2 pieces of information. When reading user input, record the number and its length or textual width.
" " to consume whitespace.
"%n" to record the offset of characters scanned so far. This does not affect the return value of scanf().
int num;
int n1, n2;
if (scanf(" %n%d%n", &n1, &num, &n2) != 1) {
puts("Failed to read an int");
}
Otherwise, print it.
"0": pad with zeros.
"*": minimum width to print derived from argument list.
else {
int length = n2 - n1;
printf("%0*d\n", length, num);
}
Input/output
007
007
The result of using scanf specifiers d, i, o, u, x, a, e, f, g is a mathematical number. There are no leading zeros. Conceptually, there are no digits in a number; it is a pure mathematical entity. (As Jonathan Leffler notes, leading zeros in the input matter the i specifier; a leading zero changes the base to octal while interpreting the numeral. This is for input only; the result is still a number with no associated digits or base.)
To preserve the leading zeros of a numeral, you must treat it as a string. scanf can be used to read strings or individual characters with the s, c, and [ specifiers, although you might wish to use a simple get-character function such as getchar. You would have to count the leading zeros yourself. The remaining digits could also be handled as a string, or you could convert them to a number.
If you store the number as an integer (e.g., int) or floating point type, any formatting information is inevitably lost: only the binary representation of the number is stored. (It may help to consider it as saving the idea of the number, e.g., "two", not how it looks when written.)
You need to store any additional information elsewhere, such as by saving the original string and using that for output, or by saving the number of digits and applying that to the printf format. There are also decimal number libraries that can internally save the decimal representation of the number, but that is considerably heavier than using the native types.
(Alternatively, just settle on a canonical output format and use that regardless of input. Is the goal really to preserve any input formatting as is, or would it suffice to always add the leading zeroes to the output?)
As already explained, numbers don't have leading zeros.
You can however treat it as a string
printf("Enter num: ");
char buf[50];
scanf("%s", &buf);
printf("You entered: %s", buf);
If you've got an int value, internally it's always represented as a certain number of bits (or whatever your CPU uses to store numbers) so you have no control over this.
There's always "leading zeroes" in terms of the internal format, because, for example, because 2099 is actually 0b00000000000000000000100000110011 in 32-bit form. This gets more complicated due to endian issues, but the principle still holds.
The only time leading zeroes makes sense is if you're using binary coded decimal, which has fallen out of style, or string notation such as produced by sprintf type functions.
It's only humans that care about digits. As far as a computer's concerned it's equally difficult to add 1+1 as it is 6916863870493370158+6471945999301299985 because they're both 64-bit operations.

Using sscanf for an unknown number of variables

For a school assignment, I have to read in a string that has at least one but up to three variables(named command, one, and two). There is always a character at the beginning of the string, but it may or may not be followed by integers. The format could be like any of the following:
i 5 17
i 3
p
d 4
I am using fgets to read the string from the file, but I'm having trouble processing it. I've been trying to use sscanf, but I'm getting segfaults reading in a string that only has one or two variables instead of three.
Is there a different function I should be using?
Or is there a way to format sscanf to do what I need?
I've tried sscanf(buffer, "%c %d %d", command, one, two) and several variations with no luck.
sscanf is probably up to this task, depending on the exact requirements and ranges of inputs.
The key here is is that the scanf family functions returns a useful value which indicates how many conversions were made. This can be less than zero: the value EOF (a negative value) can be returned if the end of the input occurs or an I/O error, before the first conversion is even attempted.
Note that the %c conversion specifier doesn't produce a null-terminated string. By default, it reads only one character and stores it through the argument pointer. E.g.
char ch;
sscanf("abc", "%c", &ch);
this will write the character 'a' into ch.
Unless you have an iron-clad assurance that the first field is always one character wide, it's probably better to read it as a string with %s. Always use a maximum width with %s not to overflow the destination buffer. For instance:
char field1[64]; /* one larger than field width, for terminating null */
sscanf(..., "%63s", field1, ...);
sscanf doesn't perform any overflow checks on integers. If %d is used to scan a large negative or positive value that doesn't fit into int, the behavior is simply undefined according to ISO C. So, just like with %s, %d is best used with a field width limitation. For instance, %4d for reading a four digit year. Four decimal digits will not overflow int.

read 2 bytes in hexadecimal base and convert into decimal using C language fscanf

Well as said Im using C language and fscanf for this task but it seems to make the program crash each time then its surely that I did something wrong here, I havent dealed a lot with this type of input read so even after reading several topics here I still cant find the right way, I have this array to read the 2 bytes
char p[2];
and this line to read them, of course fopen was called earlier with file pointer fp, I used "rb" as read mode but tried other options too when I noticed this was crashing, Im just saving space and focusing in the trouble itself.
fscanf(fp,"%x%x",p[0],p[1]);
later to convert into decimal I have this line (if its not the EOF that we reached)
v = strtol(p, 0, 10);
Well v is mere integer to store the final value we are seeking. But the program keeps crashing when scanf is called or I think thats the case, Im not compiling to console so its a pitty that I cant output what has been done and what hasnt but in debugger it seems like crashing there
Well I hope you can help me out in this, Im a bit lost regarding this type of read/conversion any clue will help me greatly, thanks =).
PS forgot to add that this is not homework, a friend want to make some file conversion for a game and this code will manipulate the files needed alone, so while I could be using any language or environment for this, I always feel better in C language
char strings in C are really called null-terminated byte strings. That null-terminated part is important, as it means a string of two characters needs space for three characters to include the null-terminator character '\0'. Not having the terminator means string functions will go out of bounds in their search for it, leading to undefined behavior.
Furthermore the "%x" format is to read a heaxadecimal integer number and store it in an int. Mismatching format specifiers and arguments leads to undefined behavior.
Lastly and probably what's causing the crash: The scanf family of function expects pointers as their arguments. Not providing pointers will again lead to undefined behavior.
There are two solutions to the above problems:
Going with code similar to what you already use, first of all you must make space for the terminator in the array. Then you need to read two characters. Lastly you need to add the terminator:
char p[3] = { 0 }; // String for two characters, initialized to zero
// The initialization means that we don't need to explicitly add the terminator
// Read two characters, skipping possible leading white-space
fscanf(fp," %c%c",p[0],p[1]);
// Now convert the string to an integer value
// The string is in base-16 (two hexadecimal characters)
v = strtol(p, 0, 16);
Read the hexadecimal value into an integer directly:
unsigned int v;
fscanf(fp, "%2x", &v); // Read as hexadecimal
The second alternative is what I would recommend. It reads two characters and parses it as a hexadecimal value, and stores the result into the variable v. It's important to note that the value in v is stored in binary! Hexadecimal, decimal or octal are just presentation formats, internally in the computer it will still be stored in binary ones and zeros (which is true for the first alternative as well). To print it as decimal use e.g.
printf("%d\n", v);
You need to pass to fscanf() the address of a the variable(s) to scan into.
Also the conversion specifier need to suite the variable provided. In your case those are chars. x expects an int, to scan into a char use the appropriate length modifiers, two times h here:
fscanf(fp, "%hhx%hhx", &p[0], &p[1]);
strtol() expects a C-string as 1st parameter.
What you pass isn't a C-string, as a C-string ought to be 0-terminated, which p isn't.
To fix this you could do the following:
char p[3];
fscanf(fp, "%x%x", p[0], p[1]);
p[2] = '\0';
long v = strtol(p, 0, 10);

take a specific number from a txt file in c program

I have this .txt file that contains only:
THN1234 54
How can I take only the number 54, to isolate it from the rest and to use it as an integer variable in my program?
If the input is from standard input, then you could use:
int value;
if (scanf("%*s %d", &value) != 1)
…Oops - incorrectly formatted data…
…use value…
The %*s reads but discards optional leading blanks and a sequence of one or more non-blanks (THN1234); the blank skips more optional blanks; the %d reads the integer, leaving a newline behind in the input buffer. If what follows the blank is not convertible to a number, or if you get EOF, you get to detect it in the if condition and report it in the body of the if.
Hmmm…and I see that BLUEPIXY said basically the same (minus the explanation) in their comment, even down to the choice of integer variable name.
Wow. It's been a long time since I have used C. However, I think the answer is similar for C and C++ in this case. You can use strtok_r to split the string into tokens then take the second token and parse it into an int. See http://www.cplusplus.com/reference/clibrary/cstring/strtok/.
You might also want to look at this question as well.

Trouble reading from file

So I think this should be pretty straight forward. I actually can't even understand what could possibly be going wrong, and that's what bugs me the most.
Here's the deal: I have to read a couple of numbers from a file, but these numbers are in scientific notation. An example file would have the numbers like this:
1.00090E+00,2.90000E+00
So I thought I'd simply read it like this: get a double, ignore a character, get an int, ignore a character, get another double, ignore a character, and get a final int, so for this example, it would:
get (1.00090)
ignore (E)
get (+00)
ignore (,)
get (2.90000)
ignore (E)
get (+00)
So, I wrote these fscanf:
fscanf(arquivo, " %lf%*c%d%*c", &mantissa1, &expoente1);
x[i] = numToFloat(mantissa1, expoente1);
fscanf(arquivo, "%lf%*c%d", &mantissa2, &expoente2);
fx[i] = numToFloat(mantissa2, expoente2);
I separated them to make the understanding simpler. But then, it doesn't work. It reads the first double correctly, but then it messes up the int. And then it messes up everything on the second fscanf.
I tried all that I could think of. Put the formatted string onto the fscanf ("%lfE%d," and "%lfE%d"). To read the signal into a character variable ("%lf%*c%c%d%*c"). None of it works.
Any guesses as to what's wrong?
First, you do not need to parse the mantissa and exponent separately. scanf natively understands n.nnnE±nnn notation. This is why your format string doesn't behave as you expect; the %lf directive consumes the entire first number including the E+00 piece, then %*c consumes the comma, %d the 2, and now we're hopelessly out of sync.
Second, you should not use any of thescanf functions, ever. Instead, read a line at a time with fgets (or getline, if you have it), split it on commas with strtok, and convert numbers to binary with strtod (which also natively understands scientific notation). This will be more coding up front, but the result will be easier to read and debug, it will be easier to make it robust against malformed input, and it will have well-defined behavior on input overflow.
(Technically you do not need to use strtok, as strtod will tell you where each number ends, but it is conceptually simpler to do the splitting first.)
You might be able to adapt this example to your needs, it used the %lg format specifier:
#include <stdio.h>
int main(void){
double d, e;
int n;
printf("Enter 2 scientific floats: ");
fflush(stdout);
n = scanf("%lg %*c %lg", &d, &e);
if(n == 2) {
printf("%f\n", d);
printf("%f\n", e);
} else {
printf("Bad input\n");
}
}
Program session
Enter 2 scientific floats: 1.8e+4,4.2e-1
18000.000000
0.420000

Resources