Help needed for basic C input and output - c

I need to get two inputs- hexadecimal address and number of bits- and then I need to print out the index and the offset of the address.
Thus, If the inputs are 20 and 0x0FF10100, the output should be 0x0FF1 for index and 0100 for the offset.
int bits, index, offset, count;
short addr[10], addr2;
printf("# of bits: ");
scanf("%d", &bits);
index = (bits / 4) + 2;
offset = 10 - index;
printf("Integer (in hex): ");
scanf("%hi", addr);
Then I need to output the index which is (20/4)+2 = 7 that means first 7 characters of the address. And the rest as offset.
I could not use printf i tried many times. But i could not fix I hope someone could help
Thanks everyone.
For output I tried to use
while (count < index)
{
printf("", addr[count], addr[count]);
count++;
}
It did not print out anything...
then I tried many variations of that and I got error. I dont know what to use to output..
Thanks

Maybe I'm missing something, but your printf call is using an empty string instead of a format string. You can see the various format specifiers here.

Always check the return value of scanf if you intend on using the input; it will return the number of items that it has successfully scanned. If you ignore the return value, you risk attempting to read indeterminate values, which means your program has undefined behaviour.
Also, in your second call to scanf, you aren't asking for a hexadecimal integer, you are asking for a short integer (h means short, and i means integer). If you want to scan a hexadecimal short integer, you need to use hx, but this also means you need to provide the address of an unsigned short, rather than a plain short.
int bits, index, offset, count;
unsigned short addr[10], addr2;
printf("# of bits: ");
if (scanf("%d", &bits) != 1)
{
// could not scan
// handle scan error here. Exit, or try again, etc.
}
index = (bits / 4) + 2;
offset = 10 - index;
printf("Integer (in hex): ");
if (scanf("%hx", addr) != 1)
{
// could not scan
// do whatever makes sense on scan failure.
}
If you are reading into consecutive elements of your addr array, you might want the following instead:
printf("Integer (in hex): ");
if (scanf("%hx", &addr[count]) != 1)
{
// could not scan
// do whatever makes sense on scan failure.
}
Finally regarding your use of printf: the first argument to printf tells it how to print the provided data. You have given it an empty string which means printf is not told to print anything. Perhaps you are looking for something like this:
printf("%d: %hx", count, addr[count]);

Related

C - Print ASCII Value for Each Character in a String

I'm new to C and I'm trying to write a program that prints the ASCII value for every letter in a name that the user enters. I attempted to store the letters in an array and try to print each ASCII value and letter of the name separately but, for some reason, it only prints the value of the first letter.
For example, if I write "Anna" it just prints 65 and not the values for the other letters in the name. I think it has something to do with my sizeof(name)/sizeof(char) part of the for loop, because when I print it separately, it only prints out 1.
I can't figure out how to fix it:
#include <stdio.h>
int main(){
int e;
char name[] = "";
printf("Enter a name : \n");
scanf("%c",&name);
for(int i = 0; i < (sizeof(name)/sizeof(char)); i++){
e = name[i];
printf("The ASCII value of the letter %c is : %d \n",name[i],e);
}
int n = (sizeof(name)/sizeof(char));
printf("%d", n);
}
Here's a corrected, annotated version:
#include <stdio.h>
#include <string.h>
int main() {
int e;
char name[100] = ""; // Allow for up to 100 characters
printf("Enter a name : \n");
// scanf("%c", &name); // %c reads a single character
scanf("%99s", name); // Use %s to read a string! %99s to limit input size!
// for (int i = 0; i < (sizeof(name) / sizeof(char)); i++) { // sizeof(name) / sizeof(char) is a fixed value!
size_t len = strlen(name); // Use this library function to get string length
for (size_t i = 0; i < len; i++) { // Saves calculating each time!
e = name[i];
printf("The ASCII value of the letter %c is : %d \n", name[i], e);
}
printf("\n Name length = %zu\n", strlen(name)); // Given length!
int n = (sizeof(name) / sizeof(char)); // As noted above, this will be ...
printf("%d", n); // ... a fixed value (100, as it stands).
return 0; // ALWAYS return an integer from main!
}
But also read the comments given in your question!
This is a rather long answer, feel free to skip to the end for the code example.
First of all, by initialising a char array with unspecified length, you are making that array have length 1 (it only contains the empty string). The key issue here is that arrays in C are fixed size, so name will not grow larger.
Second, the format specifier %c causes scanf to only ever read one byte. This means that even if you had made a larger array, you would only be reading one byte to it anyway.
The parameter you're giving to scanf is erroneous, but accidentally works - you're passing a pointer to an array when it expects a pointer to char. It works because the pointer to the array points at the first element of the array. Luckily this is an easy fix, an array of a type can be passed to a function expecting a pointer to that type - it is said to "decay" to a pointer. So you could just pass name instead.
As a result of these two actions, you now have a situation where name is of length 1, and you have read exactly one byte into it. The next issue is sizeof(name)/sizeof(char) - this will always equal 1 in your program. sizeof char is defined to always equal 1, so using it as a divisor causes no effect, and we already know sizeof name is equal to 1. This means your for loop will only ever read one byte from the array. For the exact same reason n is equal to 1. This is not erroneous per se, it's just probably not what you expected.
The solution to this can be done in a couple of ways, but I'll show one. First of all, you don't want to initialize name as you do, because it always creates an array of size 1. Instead you want to manually specify a larger size for the array, for instance 100 bytes (of which the last one will be dedicated to the terminating null byte).
char name[100];
/* You might want to zero out the array too by eg. using memset. It's not
necessary in this case, but arrays are allowed to contain anything unless
and until you replace their contents.
Parameters are target, byte to fill it with, and amount of bytes to fill */
memset(name, 0, sizeof(name));
Second, you don't necessarily want to use scanf at all if you're reading just a byte string from standard input instead of a more complex formatted string. You could eg. use fgets to read an entire line from standard input, though that also includes the newline character, which we'll have to strip.
/* The parameters are target to write to, bytes to write, and file to read from.
fgets writes a null terminator automatically after the string, so we will
read at most sizeof(name) - 1 bytes.
*/
fgets(name, sizeof(name), stdin);
Now you've read the name to memory. But the size of name the array hasn't changed, so if you used the rest of the code as is you would get a lot of messages saying The ASCII value of the letter is : 0. To get the meaningful length of the string, we'll use strlen.
NOTE: strlen is generally unsafe to use on arbitrary strings that might not be properly null-terminated as it will keep reading until it finds a zero byte, but we only get a portable bounds-checked version strnlen_s in C11. In this case we also know that the string is null-terminated, because fgets deals with that.
/* size_t is a large, unsigned integer type big enough to contain the
theoretical maximum size of an object, so size functions often return
size_t.
strlen counts the amount of bytes before the first null (0) byte */
size_t n = strlen(name);
Now that we have the length of the string, we can check if the last byte is the newline character, and remove it if so.
/* Assuming every line ends with a newline, we can simply zero out the last
byte if it's '\n' */
if (name[n - 1] == '\n') {
name[n - 1] = '\0';
/* The string is now 1 byte shorter, because we removed the newline.
We don't need to calculate strlen again, we can just do it manually. */
--n;
}
The loop looks quite similar, as it was mostly fine to begin with. Mostly, we want to avoid issues that can arise from comparing a signed int and an unsigned size_t, so we'll also make i be type size_t.
for (size_t i = 0; i < n; i++) {
int e = name[i];
printf("The ASCII value of the letter %c is : %d \n", name[i], e);
}
Putting it all together, we get
#include <stdio.h>
#include <string.h>
int main() {
char name[100];
memset(name, 0, sizeof(name));
printf("Enter a name : \n");
fgets(name, sizeof(name), stdin);
size_t n = strlen(name);
if (n > 0 && name[n - 1] == '\n') {
name[n - 1] = '\0';
--n;
}
for (size_t i = 0; i < n; i++){
int e = name[i];
printf("The ASCII value of the letter %c is : %d \n", name[i], e);
}
/* To correctly print a size_t, use %zu */
printf("%zu\n", n);
/* In C99 main implicitly returns 0 if you don't add a return value
yourself, but it's a good habit to remember to return from functions. */
return 0;
}
Which should work pretty much as expected.
Additional notes:
This code should be valid C99, but I believe it's not valid C89. If you need to write to the older standard, there are several things you need to do differently. Fortunately, your compiler should warn you about those issues if you tell it which standard you want to use. C99 is probably the default these days, but older code still exists.
It's a bit inflexible to be reading strings into fixed-size buffers like this, so in a real situation you might want to have a way of dynamically increasing the size of the buffer as necessary. This will probably require you to use C's manual memory management functionality like malloc and realloc, which aren't particularly difficult but take greater care to avoid issues like memory leaks.
It's not guaranteed the strings you're reading are in any specific encoding, and C strings aren't really ideal for handling text that isn't encoded in a single-byte encoding. There is support for "wide character strings" but probably more often you'll be handling char strings containing UTF-8 where a single codepoint might be multiple bytes, and might not even represent an individual letter as such. In a more general-purpose program, you should keep this in mind.
If we need write a code to get ASCII values of all elements in a string, then we need to use "%d" instead of "%c". By doing this %d takes the corresponding ascii value of the following character.
If we need to only print the ascii value of each character in the string. Then this code will work:
#include <stdio.h>
char str[100];
int x;
int main(){
scanf("%s",str);
for(x=0;str[x]!='\0';x++){
printf("%d\n",str[x]);
}
}
To store all corresponding ASCII value of character in a new variable, we need to declare an integer variable and assign it to character. By this way the integer variable stores ascii value of character. The code is:
#include <stdio.h>
char str[100];
int x,ascii;
int main(){
scanf("%s",str);
for(x=0;str[x]!='\0';x++){
ascii=str[x];
printf("%d\n",ascii);
}
}
I hope this answer helped you.....😊

Is it possible to make some loop which scans always one number and one string more than once? (Part of my homework)

so in my CS course we have to make a calculator which reads input and then calculates the result after the = sign has been read.
Input always consists of one number followed by operator.
I'm now struggling with the way of scanning the input. I want to use some loop which would always store it like:
scanf("%lf %s ", &in, c);
Note: the calculator goes one operation after other. Thus in example below the plus sign works only for 20 and 4, and only then the result takes the division sign and gets divided by 8. Then the new result gets negated by 'neg' string.
E.g.: Input: 20 + 4 / 8 neg =
Output: Result: -3
This is how I tried to solve it. My intention was to make the loop store each number into a new "box" of array, and then to store each string into the new "line" of char array. The 4 in op array is meant to set the max length of the string, because i know that the longest string that can occur is "sqrt".
I see that the '\n' in the condition of for is probably useless but can't figure out how to do it...
I'm thinking about using either for, or a while loop.
int main(){
double in[10];
char op[5][4];
for(int i=0; i<5;i++){
scanf("%lf %s ", &in[i], op[i][4]);
}
printf("%.3f %s", in[0], op[0][0]);
return 0;
}
//just a "skeleton" of the code. There's more to it, but here I submitted just the part that I'm struggling with.
For example if I run this code, I want to write a few numbers followed by operator into the input.
I expect it to print the first number and string (just to check whether the loop works).
But actually it does absolutely nothing and just gives me some large negative number as a return.
From the man page of scanf
int scanf(const char *format, ...);
as you can see first argument is of const char * type i.e you need to provide valid address.
With this
char op[5][4]; /* 5 char array, in each char array you can have 4 char's
* i.e op[row][0] to op[row][3]. There is no op[i][4]
*/
you can have
for(int i=0; i<5;i++){
scanf("%s",op[i]); /* op[i] itself address, so don't need & */
}
or
for(int i=0; i<5;i++){
for(int j=0; j<4; j++) {
scanf(" %c", &op[i][j]); /* storing char by char */
}
}
Also while printing here use %c as op[0][0] is of char type.
printf("%.3f %c", in[0], op[0][0]);
In a scanf format string, %s indicates you want to read a string, meaning it needs the address of where to put that string. You are passing op[i][4] for it, which is a char.

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!

Formatting very large numbers in C

I have to output a large number, a double precision number using the following code:
fprintf(outFile," %11.0f %d O(g(n))",factorialNotRecursive(index,factCount),factValue);
now the number gets so big that it jumps out of alignment further down the
list of output. Once it gets past 11 digits, the max specified it continues
to grow larger. Is there a way to cope with this? I'm not sure how big the inputs
that will be run on this program.
I think you cannot do it directly. You have to print to a string, then change the string.
/* pseudo (untested) code */
value = factorialNotRecursive(index, factCount);
/* make sure buff is large enough (or use snprintf if available) */
n = sprintf(buff, "%11.0f", value);
if (n > 11) {
buff[10] = '+';
buff[11] = 0;
}
fprintf(outFile," %s %d O(g(n))", buff, factValue);

How do I read hex numbers into an unsigned int in C

I'm wanting to read hex numbers from a text file into an unsigned integer so that I can execute Machine instructions. It's just a simulation type thing that looks inside the text file and according to the values and its corresponding instruction outputs the new values in the registers.
For example, the instructions would be:
1RXY -> Save register R with value in
memory address XY
2RXY -> Save register R with value XY
BRXY -> Jump to register R if xy is
this and that etc..
ARXY -> AND register R with value at
memory address XY
The text file contains something like this each in a new line. (in hexidecimal)
120F
B007
290B
My problem is copying each individual instruction into an unsigned integer...how do I do this?
#include <stdio.h>
int main(){
FILE *f;
unsigned int num[80];
f=fopen("values.txt","r");
if (f==NULL){
printf("file doesnt exist?!");
}
int i=0;
while (fscanf(f,"%x",num[i]) != EOF){
fscanf(f,"%x",num[i]);
i++;
}
fclose(f);
printf("%x",num[0]);
}
You're on the right track. Here's the problems I saw:
You need to exit if fopen() return NULL - you're printing an error message but then continuing.
Your loop should terminate if i >= 80, so you don't read more integers than you have space for.
You need to pass the address of num[i], not the value, to fscanf.
You're calling fscanf() twice in the loop, which means you're throwing away half of your values without storing them.
Here's what it looks like with those issues fixed:
#include <stdio.h>
int main() {
FILE *f;
unsigned int num[80];
int i=0;
int rv;
int num_values;
f=fopen("values.txt","r");
if (f==NULL){
printf("file doesnt exist?!\n");
return 1;
}
while (i < 80) {
rv = fscanf(f, "%x", &num[i]);
if (rv != 1)
break;
i++;
}
fclose(f);
num_values = i;
if (i >= 80)
{
printf("Warning: Stopped reading input due to input too long.\n");
}
else if (rv != EOF)
{
printf("Warning: Stopped reading input due to bad value.\n");
}
else
{
printf("Reached end of input.\n");
}
printf("Successfully read %d values:\n", num_values);
for (i = 0; i < num_values; i++)
{
printf("\t%x\n", num[i]);
}
return 0
}
You can also use the function strtol(). If you use a base of 16 it will convert your hex string value to an int/long.
errno = 0;
my_int = strtol(my_str, NULL, 16);
/* check errno */
Edit: One other note, various static analysis tools may flag things like atoi() and scanf() as unsafe. atoi is obsolete due to the fact that it does not check for errors like strtol() does. scanf() on the other hand can do a buffer overflow of sorts since its not checking the type sent into scanf(). For instance you could give a pointer to a short to scanf where the read value is actually a long....and boom.
You're reading two numbers into each element of your array (so you lose half of them as you overwrite them. Try using just
while (i < 80 && fscanf(f,"%x",&num[i]) != EOF)
i++;
for your loop
edit
you're also missing the '&' to get the address of the array element, so you're passing a random garbage pointer to scanf and probably crashing. The -Wall option is your friend.
In this case, all of your input is upper case hex while you are trying to read lower case hex.
To fix it, change %x to %X.
Do you want each of the lines (each 4 characters long) separated in 4 different array elements? If you do, I'd try this:
/* read the line */
/* fgets(buf, ...) */
/* check it's correct, mind the '\n' */
/* ... strlen ... isxdigit ... */
/* put each separate input digit in a separate array member */
num[i++] = convert_xdigit_to_int(buf[j++]);
Where the function convert_xdigit_to_int() simply converts '0' (the character) to 0 (an int), '1' to 1, '2' to 2, ... '9' to 9, 'a' or 'A' to 10, ...
Of course that pseudo-code is inside a loop that executes until the file runs out or the array gets filled. Maybe putting the fgets() as the condition for a while(...)
while(/*there is space in the array && */ fgets(...)) {
}

Resources