String input into int array -- C - c

I'm trying to write a program that will convert a floating point number into its IEEE 754 single representation and vice versa. I'm stuck on how to take the input, which will be in the form "0xABCD123" or "2.83234e-2" (with the hex representation always preceded by "0x"), and take each element and put it into a char array.
For example, the input "0xABCD123" will be in a char array of size 10. I will remove the "0" and "x" elements, and then go through each element individually and convert into floating point from there with the use of a for loop.
Getting the argument from the command line is simple enough I think. The argument is stored in argv[1], then I save that into an initialized string variable called input. The problem is taking input and putting each element into a character array. The second problem is determining the length of the array if the input is not in IEEE format. I haven't found a function that determines the length of a string (removing decimals points and account for the 'e').
Also, a couple questions: Does C automatically recognize the "e-2" part of an input and translate that into the actual number? Is there some command I can use to do that?
How would type casting work here? If the input was "2.83234e3", and I wanted to save the part to the left of the decimal point as an int (because that would be easier to translate), and then the left as an int as well, how would I split up the number through type casting? Would it be something like input = (int)left;?

Related

What happens when we make an array defined using characters instead of integers in C?

This is a code I have used to define an array:
int characters[126];
following which I wanted to get a record of the frequencies of all the characters recorded for which I used the while loop in this format:
while((a=getchar())!=EOF){
characters[a]=characters[a]+1;
}
Then using a for loop I print the values of integers in the array.
How exactly is this working?
Does C assign a specific number for letters ie. a,b,c, etc in the array?
What happens when we make an array defined using characters instead of integers in C?
Let's be sure we are clear: you are using integer values returned by getchar() as indexes into your array. This is not defining the array, it is just accessing its elements.
Does C assign a specific number for letters ie. a,b,c, etc in the array?
There are no letters in the array. There are ints. However, yes, the characters read by getchar() are encoded as integer values, so they are, in principle, suitable array indexes. Thus, this line ...
characters[a]=characters[a]+1;
... reads the int value then stored at index a in array characters, adds 1 to it, and then assigns the result back to element a of the array, provided that the value of a is a valid index into the array.
More generally, it is important to understand that although one of its major uses is to represent characters, type char is an integer type. Its values are numbers. The mapping from characters to numbers is implementation and context dependent, but it is common enough for the mapping to be consistent with the ASCII code that you will often see programs that assume such a mapping.
Indeed, your code makes exactly such an assumption (and others) by allowing only for character codes less than 126.
You should also be aware that if your characters array is declared inside a function then it is not initialized. The code depends on all elements to be initially to zero. I would recommend this declaration instead:
int characters[UCHAR_MAX + 1] = {0};
That upper bound will be sufficient for all the non-EOF values returned by getchar(), and the explicit zero-initialization will ensure the needed initial values regardless of where the array is declared.
I have realized the charecter set that can function as an input for getchar() is part of the ASCII table and comes under an int. I used the code following to find that out:
#include <stdio.h>
int main(){
int a[128];
a['b']=4;
printf("%d",a[98]); //it is 98 as according to the table 'b' is assigned the value of 98
}
following which executing this code i get the output of 4.
I am really new to coding so feel free to correct me.
Character values are represented using some kind of integer encoding - ASCII (very common), EBCDIC (mostly IBM mainframes), UTF-8 (backward-compatible to ASCII), etc.
The character value 'a' maps to some integer value - 97 in ASCII and UTF-8, 129 in EBCDIC. So yes, you can use a character value to index into an array - arr['a']++ would be equivalent to arr[97]++ if you were using ASCII or UTF-8.
The C language does not dictate this - it's determined by the underlying platform.

Print number with zero on first place

How i can print for example?
int a = 0145236
When I want to use it, it always gives me a octal number.
Whenever you put zero in front of your number it is printed in octal only. That is the way c works.
However, if you take input from the user and supposing user entered 0123456 it is stored in your variable as 123456 so just don't add 0 in the beginning of your integer number when hard coding.
In case you need to add leading zeros in your number this may help Printing leading 0's in C?

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);

incompatible types in assignment of `float' to `char[3]'

trying to figure out what is going on here. I'm just learning C, so go easy on me. :P I was assigned to create a unit converter from centimeters to inches. I've got it. Now I want to spice it up a little by creating options. My compiler isn't enjoying what I have. this is the first few lines....
main(void)
{
float centimeter;
char cnv[3];
float entry;
float oz;
float lb;
float cm;
float lb1;
centimeter=2.54;
lb1=2.2;
printf("Hello. Please type exactly, the type of conversion you would like to do.\n\n1. cm to in\n\n2. lb to kg\n");
scanf("%3c",&cnv);
if (strcmp(cnv=cm));
{
printf("Please enter your length in centimeters:\n");
scanf("%f",&entry);
printf("with %.0f centimeters in length, that converts to %.2f inches.",entry,entry/centimeter);
}
if (strcmp(cnv=lb));
{
printf("Please enter your weight in pounds:\n");
scanf("%f",&entry);
printf("with %.0f Pound(s) of weight, that converts to %.2f Kilogram(s).",entry,entry/lb1);
}
}
and it's giving me the error in the title. How can I fix this?
1) You're confusing = (assignment) with == (test for equality)
2) You can't compare a numeric value directly to a character array. You need to convert one or the other to a type which can be compared -- convert the number to string, if your using strcmp() (and understand how that function returns its results, which aren't what you've assumed here), or convert the string to a numeric type and compare that way.
The '=' operator is used for assigning values not comparison. You should use '==' for comparisons.
The values that you are of different types. You should convert one of the variables to the other type to compare.
Strings must be compared with some string comparison function like strcmp() as you have done, but strcmp() is a function and therefore the you should pass the parameters in with a comma separating them.
As an aside strcmp() returns 0 when the strings that you pass in are equivalent, so using a syntax more like this would be appropriate: if(!strcmp(cnv, cm)) or if(strcmp(cnv, cm) == 0)
If I might take a guess what you really were looking to do was something like: if(strcmp(cnv, "cm") == 0) cm is a name of a variable whereas "cm" is a zero terminated string with the characters 'c' and 'm'
The next thing that you will need to worry about is reading in the 3 characters from scanf, because if the input was "cm" and the user pressed enter to enter the text. The program scanned 3 characters one of which was the newline character '\n'. So when you go to do the strcmp() the program will compare each character up till it reaches a byte that has been zeroed out. With just 3 characters being read I am not sure if the string you are capturing is zero terminated, but I am sure that the string could contain a '\n' which would throw the results of strcmp() way off.
Thestrcmp syntax is not correct. For more about string compare function please check this link
http://www.tutorialspoint.com/ansi_c/c_strcmp.htm

New to C: whats wrong with my program?

I know my way around ruby pretty well and am teaching myself C starting with a few toy programs. This one is just to calculate the average of a string of numbers I enter as an argument.
#include <stdio.h>
#include <string.h>
main(int argc, char *argv[])
{
char *token;
int sum = 0;
int count = 0;
token = strtok(argv[1],",");
while (token != NULL)
{
count++;
sum += (int)*token;
token = strtok(NULL, ",");
}
printf("Avg: %d", sum/count);
printf("\n");
return 0;
}
The output is:
mike#sleepycat:~/projects/cee$ ./avg 1,1
Avg: 49
Which clearly needs some adjustment.
Any improvements and an explanation would be appreciated.
Look for sscanf or atoi as functions to convert from a string (array of characters) to an integer.
Unlike higher-level languages, C doesn't automatically convert between string and integral/real data types.
49 is the ASCII value of '1' char.
It should be helpful to you....:D
The problem is the character "1" is 49. You have to convert the character value to an integer and then average.
In C if you cast a char to an int you just get the ASCII value of it. So, you're averaging the ascii value of the character 1 twice, and getting what you'd expect.
You probably want to use atoi().
EDIT: Note that this is generally true of all typecasts in C. C doesn't reinterpret values for you, it trusts you to know what exists at a given location.
strtok(
Please, please do not use this. Even its own documentation says never to use it. I don't know how you, as a Ruby programmer, found out about its existence, but please forget about it.
(int)*token
This is not even close to doing what you want. There are two fundamental problems:
1) A char* does not "contain" text. It points at text. token is of type char*; therefore *token is of type char. That is, a single byte, not a string. Note that I said "byte", not "character", because the name char is actually wrong - an understandable oversight on the part of the language designers, because Unicode did not exist back then. Please understand that char is fundamentally a numeric type. There is no real text type in C! Interpreting a sequence of char values as text is just a convention.
2) Casting in C does not perform any kind of magical conversions.
What your code does is to grab the byte that token points at (after the strtok() call), and cast that numeric value to int. The byte that is rendered with the symbol 1 actually has a value of 49. Again, interpreting a sequence of bytes as text is just a convention, and thus interpreting a byte as a character is just a convention - specifically, here we are using the convention known as ASCII. When you hit the 1 key on your keyboard, and later hit enter to run the program, the chain of events set in motion by the command window actually passed a byte with the value 49 to your program. (In the same way, the comma has a value of 44.)
Both of the above problems are solved by using the proper tools to parse the input. Look up sscanf(). However, you don't even want to pass the input to your program this way, because you can't put any spaces in the input - each "word" on the command line will be passed as a separate entry in the argv[] array.
What you should do, in fact, is take advantage of that, by just expecting each entry in argv[] to represent one number. You can again use sscanf() to parse each entry, and it will be much easier.
Finally:
printf("Avg: %d", sum/count)
The quotient sum/count will not give you a decimal result. Dividing an integer by another integer yields an integer in C, discarding the remainder.
In this line: sum += (int)*token;
Casting a char to an int takes the ASCII value of the char. for 1, this value is 49.
Use the atoi function instead:
sum += atoi(token);
Note atoi is found in the stdlib.h file, so you'll need to #include it as well.
You can't convert a string to an integer via
sum += (int)*token;
Instead you have to call a function like atoi():
sum += atoi (token);
when you cast a char (which is what *token is) to int you get its ascii value in C - which is 49... so the average of the chars ascii values is in fact 49. you need to use atoi to get the value of the number represented

Resources