sprintf(array, "%4d\n", int), turning it back into an int - c

I'm having trouble understanding how this piece of code formats an int to a string:
length[16];
sprintf(length, "%4d\n", len );
length[5]=0;
UDP_Write( sd, &cli, length, 6);
I then need to turn length back to an int, but how? If, for example, len == 512, isn't length gonna be filled like this: 0512x0? How do I turn it back to an int if there's a character in length that I don't know of its' contents?

For input int 512, the result of the code is the string " 512\n". There's no zeroes or letters in there, not sure where you got that idea from.
To convert string to int, you could use any of the usual methods, e.g. sscanf, strtol etc. because they are able to ignore leading whitespace.

Related

Convert entire array of characters into integer in C

I'm reading input from a file and trying to create a numerical value from the strings I take in.
I tried simply using the atoi but that doesn't work on characters.
Then I tried using a forloop over my array of characters but then I got error because some characters are actually integers.
Then I tried using ifstatement to check if the characters themselves are integers and just add it to my "sum" manually.
But so far all I get is errors and errors, I'm not sure where my logic is wrong.
In C an array is simply a pointer right? So to access the value at a certain index I use *arr[num] right?
This is my code
char newlineC;
char input[14];
while(fscanf(fp,"%s%c",input, &newlineC)!=EOF){
int val = 0;
int x;
for(x=0; x<14; x++){
if(isdigit(*input[x])){
val = val + input[x];
}else{
int p = atoi(input[x]);
val = val + p;
}
}
I've tried the strol function... didn't work either. I've been at this for so long I feel dumb that I am stumped on something that seems so simple. Any help is appreciated.
You are passing the wrong types all over the place.
char input[14];
this declares an char array of dimension 14. input[i] is the ith char in
the array, it has type char. It's not a pointer, you cannot dereference it,
that's why *input[x] fails. In fact the compiler should have given you an
error there, this error:
invalid type argument of unary ‘*’ (have ‘int’)
The same problem with atoi. It expects a pointer to char that points to a
string. input[x] is single char, you cannot pass to atoi. Again the
compiler should have warned you.
fscanf(fp,"%s%c",input, &newlineC)
This is very clumsy. If the input is larger than 13 characters, you will
overflow the buffer. A better way would be:
fscanf(fp, "%13s%c", input, &newline);
Or even better
int val;
fscanf(fp, "%d", &val);
Another error: if you know that input[x] is a digit, then the integer that the
digit represent is input[x] - '0'. So this should be the calculation:
val = val + input[x] - '0';
Overall I would use fgets and strtol:
while(fgets(input, sizeof input, fp))
{
long int val;
char *tmp;
val = strtol(line, &tmp, 0);
if(*tmp == 0 || *tmp == '\n')
printf("An integer was read: %ld\n", val);
else
printf("More than an integer was read: '%s'\n", line);
}
If you are only converting the chars [1..0] to an integer value, all you have to do is
int main(void) {
char input[14];
scanf("%s", input);
if (isdigit(input[0])) {
int num = atoi(input);
printf("%d\n", num);
}
else {
printf("INPUT ERROR\n");
}
}
Are you wanting to process alphabet characters as well and turn them into some integer value?
Arrays in C are based on pointers, but that's not all they are. Arrays in C is just a bunch of those data types in a line in memory. That way you can just access the pointer of the lead variable, than hop down that list in order to get the next iteration of the array.
isdigit(*input[14])
This line will cause issues. Look at what input itself is. input is the pointer to your first element in that array. input is essentially saying char* input = &array[0]; So lets say you dereference that input variable without that 14, you would get the first element. So we can say that *input = array[0]; Do you see the issue here? You basically dereferenced it twice. If you had just done insdigit(input[14]) that would work a bit better.
But onto the bigger issue here. You're taking a char array, that contains only chars, and you're trying to convert them into numbers. Remember that char and int are two different data types. Go ahead and check out this table: https://upload.wikimedia.org/wikipedia/commons/d/dd/ASCII-Table.svg
Recall that chars are basically just numbers that correspond to that ASCII value. For example your computer doesn't read a letter as a D, it reads it as 68 (or the binary format of 68). For numbers it's the same concept, even if it seems like it's just a number and you should be able to add it to val, you'd first have to subtract 48 or use the atoi function on digits.
So what can you do here? I can't say for sure without knowing exactly what you're trying to do as I don't know your specific needs, but just realize that you can already convert char into ints very easily. I believe you can just add a char to an int, although I may be mistaken (I do know there's a very easy way to add a char's value though, maybe you have to cast it first?) However recall that if you want the digits to count for face value, you'd have to subtract 48 from them first.
If you want to use atoi you can, however honestly I don't see the need here, since you're already converting regular chars to numbers here. It'd be sufficient to check to see if the char value is between 48 and 58 (or whatever the actual numbers are) and if they are then you could subtract that.
Hope this helped!

How to printf a fixed length output from format

This following code:
printf("%d. %-10s:", 1, "Test");
produces this output:
1. Test :// 14 characters long
I would like the output length of the entire format `%d. %-10s:" to be exactly 10 characters like this:
1. Test: // 10 characters
Note:
The numbers vary in length, it could be 1 or 100, so I can't deduce it's length from the output.
How can I do that?
You need to use two steps:
char buffer[20];
snprintf(buffer, sizeof(buffer), "%d. %s:", 1, "Test");
printf("%-*s", 10, buffer);
The snprintf() operation give you a string 1. Test: in buffer; note that it includes the : in the output, and assumes no trailing blanks on the string "Test"). The printf() operation formats the string left justified (-) in a length of (at least) 10 (the * in the format and the 10 in the argument list) onto standard output. Presumably, something else will appear after this output on the same line; otherwise, there's no obvious point to the blank padding.
For full information, see:
snprintf()
This covers the basic operation of the *printf() family of functions (but does not list the interfaces to the v*printf() or *wprintf() families of functions).
The code in the question and in the answer above is all done with constants. A more realistic scenario would be:
void format_item(int number, const char *text, int width)
{
char buffer[width+1]; // C99 VLA
snprintf(buffer, sizeof(buffer), "%d. %s:", number, text);
printf("%-*s", width, buffer);
}
Note that this code truncates the formatted data if the number plus the string is too long. There are ways around that if you work a bit harder (like adding more than 1 to width in the definition of buffer — maybe add 15 instead of 1).
You might write:
format_item(1, "Test", 10);
or:
char *str_var = …some function call, perhaps…
int item = 56;
format_item(++item, str_var, 20);
etc.

A way to fscanf on only the first line

I've been looking into a way to obtain 2 integers, seperated by a space, that are located in the first line of a file that I would read. I considered using
fscanf(file, "%d %d\n", &wide, &high);
But that read 2 integers that were anywhere in the file, and would give the wrong output if the first line was in the wrong format. I also tried using
char line[1001];
fgets(line, 1000, file);
Which seems like the best bet, except for how clumsy it is. It leaves me with a string that has up to a few hundred blank spaces, from which I must extract my precious integers, nevermind checking for errors in formatting.
Surely there is a better option than this? I'll accept any solution, but the most robust solution seems (to me) to be a fscanf on the first line only. Any way to do that?
You can capture the character immediately following the second number in a char, and check that the captured character is '\n', like this:
int wide, high;
char c;
if (fscanf(file, "%d%d%c", &wide, &high, &c) != 3 || c != '\n') {
printf("Incorrect file format: expected two ints followed by a newline.");
}
Here is a demo on ideone.
Which seems like the best bet, except for how clumsy it is.
Nah, it's not clumsy at all (except that you are using the size argument of fgets() in the wrong way...). It's perfectly fine & idiomatic. strtol() does its job pretty well:
char line[LINE_MAX];
fgets(line, sizeof line, file);
char *endp;
int width = strtol(line, &endp, 10);
int height = strtol(endp, NULL, 10);

understanding ATOI function

Hi I have a text file which contains the below data
ABC00011234567
XYZ00021234567
To get the data, i have defined a structure
typedef struct data {
char x[3];
char y[4];
char z[7];
} key;
in the program what I do is read each line and assign it to the structure
unsigned char buf[1024];
fgets(buf,sizeof(buf),fptr);
key *k=(key*)buf;
int y = atoi(k->y)
printf( "y=%d\n",y);`
I'm getting the output as
y=1123456
y=2123456
the output Im expecting is
y=1
y=2
should I assume, atoi takes the pointer of the string and iterates till EOF is encountered?
what should I do to get the values 1 and 2?
atoi takes a nul-terminated string. You'll have to add your own terminators to your key members if you want to limit the length of data atoi parses
You should assume that atoi() keeps going until it reaches the end of the string or an invalid character. For example, for the string `"123zzz" it'd return 123.
You should either terminate your strings (put a zero at the end of them) and stop using atoi() (e.g. use strtol() instead); or write your own conversion that doesn't need a terminated string.
Note: (in general) atoi() should never be used for anything other than writing a compiler, because it does things that don't make sense to normal people (e.g. "0129" is 10 and not 129 because it decides the number is octal and the 9 isn't a valid digit for octal).
The atoi function expects a null-terminated string; you are passing a portion of the char array that has its termination past the boundaries of key::y, so atoi interprets the entire value as a number. If you would like to stick to your "cookie cutter" method of parsing the key, you need to make a copy, and pass it to atoi:
char temp[5];
memcpy(temp, k->y, 4);
temp[4] = '\0';
int y = atoi(temp);
However, I think that using fscanf is a better choice:
char x[4];
int y, z;
fscanf(fptr, "%3s%4d%7d", x, &y, &z);
printf("%s %d %d", x, y, z);
atoi() assumes a zero terminated string. In your case, the string will not be zero-terminated, and thus the data in z is read by atoi after y has been read.
To read just the 4 digits, you can use sscanf:
sscanf(k->y,"%4d",&y);

Is there any char to hexadecimal function for C?

I have a char array with data from a text file and I need to convert it to hexadecimal format.
Is there such a function for C language.
Thank you in advance!
If I understand the question correctly (no guarantees there), you have a text string representing a number in decimal format ("1234"), and you want to convert it to a string in hexadecimal format ("4d2").
Assuming that's correct, your best bet will be to convert the input string to an integer using either sscanf() or strtol(), then use sprintf() with the %x conversion specifier to write the hex version to another string:
char text[] = "1234";
char result[SIZE]; // where SIZE is big enough to hold any converted value
int val;
val = (int) strtol(text, NULL, 0); // error checking omitted for brevity
sprintf(result, "%x", val);
I am assuming that you want to be able to display the hex values of individual byes in your array, sort of like the output of a dump command. This is a method of displaying one byte from that array.
The leading zero on the format is needed to guarantee consistent width on output.
You can upper or lower case the X, to get upper or lower case representations.
I recommend treating them as unsigned, so there is no confusion about sign bits.
unsigned char c = 0x41;
printf("%02X", c);
You can use atoi and sprintf / snprintf. Here's a simple example.
char* c = "23";
int number = atoi(c);
snprintf( buf, sizeof(buf), "%x", number );

Resources