Passing int using char pointer in C - c

I'm trying to figure out how to pass an int using a char pointer. It fails once the int value is too large for the char. This is what I'm trying to figure out:
char *args[5];
int i = 20;
/*some other code/assignments*/
args[2] = (char *)&i;
execv(path, args);
How would I do something like this if i was a bigger value, like 400?
Thanks in advance.

Programs simply do not take integers as arguments, they take strings. Those strings can be decimal representations of integers, but they are still strings. So you are asking how to do something that simply doesn't make any sense.
Twenty is an integer. It's the number of things you have if you have eighteen and then someone gives you two more. Twenty cannot be a parameter to an executable.
"20" is a string. It can represent the number twenty in decimal. But it's a sequence of two characters, the decimal digit '2' followed by the decimal digit '0'.
You pass strings to executables, not integers.
When you enter a command like tail -f 20, the number twenty is not one of the arguments. They are the string "tail", the string "-f", and the string "20" (the digit '2' followed by the digit '0'). There are no numbers in there, just strings (though one of them happens to represent a number).
You can do this:
int i = 10;
char parameter[32];
sprintf(parameter, "%d", i);
// parameter now contains the string "10"
args[2] = parameter;

Related

writing a function that subtract one from string in c

I am learning C in school and am doing a project that involves writing a function(str_subtract_one) that gets a string containing a positive integer.
The function subtracts 1 from that integer and puts the obtained value in the string.
In the code below, I successfully wrote a function to do that, but the thing is that the input numbers may be larger than the maximum of int, long or long long, so I should not try to convert the string to an integer.
So, without converting the string into int, long or long long, how can I do the same job?
I appreciate any feedback. Thank you so much.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void str_subtract_one(char* num) {
char *end; // to use it in strtol function,
long long as_long = strtoll(num,&end,10); //to convert string to long, use strtol.
sprintf(num, "%lld", as_long - 1); // to convert long into string and now num has a string value
}
int main() {
char nums[] = "2462343434344545";
str_subtract_one(nums);
printf("\nstr_subtract_one function result; %s\n",nums);
return 0;
}
For example if input string is "2323", it should output "2322".
If "1000", output "999", etc.
You can use the following algorithm:
If the last character of the string is a '9', then you can change it to an '8'.
Otherwise, if the last character of the string is a '8', then you can change it to an '7'.
Otherwise, if the last character of the string is a '7', then you can change it to an '6'.
[...]
Otherwise, if the last character is a '0', you change it to a '9' and repeat all of the above with the next digit.
If you run out of digits (which will happen if all of the digits are '0'), you must overwrite the entire string with the new string "-1". This will only work if at least 3 bytes have been allocated for the string, otherwise there will be not enough room to write the result, without causing a buffer overflow. For example, if you write
char nums[] = "0";
then trying to write "-1" into the string will write to the array out of bounds, causing undefined behavior (your program may crash).
For this reason, you would have to write the following instead, if you want to ensure that there is room for writing "-1":
char nums[3] = "0";
Note that this algorithm will only work with positive numbers. (In your question, you stated that we can assume that the numbers are positive.)
If you want it to also work with negative numbers, you must first check the sign of the number and then apply the appropriate algorithm. You will need one algorithm for handling positive numbers and one for handling negative numbers (although you may want to try to combine both of them into one algorithm).
In accordance with the community guidelines on homework questions, I will not provide the full solution to your problem at this time. However, I can add code later, if required.

Calling the 1's, 10's, 100's... columns of an integer using a string array

I'm trying to convert a long long integer to a string array with the 1's column in position 0 of the array, the 10's column in position 1, the 100's column in position 2, like this:
INPUT: 4444555566667777 -----> OUTPUT: [4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7]
To test my code, I wrote for my last line printf("%d\n",number_str[3]). I expected my program to output the value of position 4, "7". Instead, it output "52". Changing my last line to printf("%d\n",number_str[4]) yields "53" instead of "6", as I expected. Can anyone explain what's going on?
Surely 52 and 53 correspond to ASCII values, but then, how can I convert them to integers? Can I do this in line?
Where I'm headed with this part of my program is to add up all of the numbers in the 10's, 1,000's, 100,000's, 10,000,000's... columns. Every other digit in a base-10 credit card number. This is one step in my attempt at a Luhn validation.
// Libraries
#include <cs50.h>
#include <stdio.h>
#include <string.h>
// Program
int main(void)
{
// Get CC number
printf("Enter your credit card number: ");
long long number_ll = GetLongLong();
// printf("%lld\n", number_ll);
// Convert long long to string
char number_str[64];
sprintf(number_str, "%lld", number_ll);
// printf("%s\n", number_str);
// Get length of card number string
int cclength = strlen(number_str);
// Check the length of card number string
if ( ! (cclength == 13 || cclength == 15 || cclength == 16))
printf("INVALID\n");
else
printf("%d\n",number_str[3]);
To convert ascii into integer use
#include <stdlib.h>
int atoi(const char *str);
change this
printf("%d\n",number_str[3]);
to
char buf[2];
buf[0]=number_str[3];
buf[1]='\0';
printf("%d\n",atoi((const char*)buf));
Using "%d" on a char will print its ASCII code. Use "%c" to print itself.
And your string's order is reversed compared to your purpose. The rightmost digit(1's column) is at the tail of the string, and the leftmost one is in position 0.
So to print the number at position i (count from right to left), you should use:
printf("%c\n", number_str[cclength - i - 1]);
I'm going to go ahead and expand on my comment since I don't believe either of the other answers responded to your full question.
By reading the CC number into a long long, and then using sprintf to plug the number into a character array, I would say you're correctly getting the number into a form that you can use for validation. In fact, you can check the return value of sprintf to see whether or not it's a valid number (although a failure case would be unlikely since you're plugging in a long long.
Once you have the CC number in a character array, you know that each element of the array will contain one character, which corresponds to one digit in the CC number. It sounds like for your purposes, it's more useful for the values in the array to be the decimal values, rather than the ASCII values. Logically, this is the difference between the values '0' and 0. You can look up any ASCII chart to see the corresponding ASCII value for each character, but since characters can be manipulated just like integers, you can traverse the array:
for(i = 0; i < 64; i++) num_str[i] -= '0';
Note that this doesn't handle there being less than 64 characters or uninitialized values in the array after the CC number characters, so you'll need to modify it. What's important to realize is that you're just shifting the character values down by '0', which happens to have the integer value 48.
Once you do this conversion, printing out a value in the array with printf using %d as the format specifier will work like you expect; even though the array data type is char, each element may be printed as a decimal integer.
Once you've read the number into the char array and made the conversion, all you need to do is traverse the array again, performing whatever steps are involved in the CC Validation process. You may need to traverse the array in reverse if the validation method requires the digits to be in order.

Differences between int/char arrays/strings

I'm still new to the forum so I apologize in advance for forum - etiquette issues.
I'm having trouble understanding the differences between int arrays and char arrays.
I recently wrote a program for a Project Euler problem that originally used a char array to store a string of numbers, and later called specific characters and tried to use int operations on them to find a product. When I used a char string I got a ridiculously large product, clearly incorrect. Even if I converted what I thought would be compiled as a character (str[n]) to an integer in-line ((int)str[n]) it did the exact same thing. Only when I actually used an integer array did it work.
Code is as follows
for the char string
char str[21] = "73167176531330624919";
This did not work. I got an answer of about 1.5 trillion for an answer that should have been about 40k.
for the int array
int str[] = {7,3,1,6,7,1,7,6,5,3,1,3,3,0,6,2,4,9,1,9};
This is what did work. I took off the in-line type casting too.
Any explanation as to why these things worked/did not work and anything that can lead to a better understanding of these ideas will be appreciated. Links to helpful stuff are as well. I have researched strings and arrays and pointers plenty on my own (I'm self taught as I'm in high school) but the concepts are still confusing.
Side question, are strings in C automatically stored as arrays or is it just possible to do so?
To elaborate on WhozCraig's answer, the trouble you are having does not have to do with strings, but with the individual characters.
Strings in C are stored by and large as arrays of characters (with the caveat that there exists a null terminator at the end).
The characters themselves are encoded in a system called ascii which assigns codes between 0 - 127 for characters used in the english language (only). Thus "7" is not stored as 7 but as the ascii encoding of 7 which is 55.
I think now you can see why your product got so large.
One elegant way to fix would be to convert
int num = (int) str[n];
to
int num = str[n] - '0';
//thanks for fixing, ' ' is used for characters, " " is used for strings
This solution subtracts the ascii code for 0 from the ascii code for your character, say "7". Since the numbers are encoded linearly, this will work (for single digit numbers). For larger numbers, you should use atoi or strtol from stdlib.h
Strings are just character arrays with a null terminating byte.
There is no separate string data type in c.
When using a char as an integer, the numeric ascii value is used. For example, saying something like printf("%d\n", (int)'a'); will result in 97 (the ascii value of 'a') being printed.
You cannot use a string of numbers to do numeric calculations unless you convert it to an integer array. To convert a digit as a character into its integer form, you can do something like this:
char a = '2';
int a_num = a - '0';
//a_num now stores integer 2
This causes the ascii value of '0' (48) to be subtracted from ascii value '2' (50), finally leaving 2.
char str[21] = "73167176531330624919"
this code is equivalent to
char str[21] = {'7','3','1','6','7','1','7','6','5',/
'3','1','3','3','0','6','2','4','9','1','9'}
so whatever stored in str[21] is not numbers, but the char(their ASCII equivalent representation is different).
side question answer - yes/no, the strings are automatically stored as char arrays, but the string does has a extra character('\0') as the last element(where a char array need not have such a one).

How to create array with hex chars from array of numbers

I have array of chars:
char macChars=[12];
The content of it is e.g. macChars[0]=53, macChars[1]=66 ...
I need to convert these numbers to hex chars, so i would have another array:
macCharsHex[0]=5 //value 53 in hex
macCharsHex[1]=B //value 66 in hex
Thank you.
Assuming ASCII, your example already does contain the values you want them to contain. So you don't have to convert anything. Maybe you want to print them?
This should work:
char hex[255] = {0}; // Varible to hold the hex value
int dec = 1234; // Decimal number to be converted
sprintf(hex,"%X", dec);
printf("%s", hex); // Print hex value
Use sprintf(), for instance. Note that it will take more space, if you have 12 bytes you will need 24 + 1 bytes for the string representation, since each byte requires two characters in hex and then the terminating '\0'-byte.
I suspect that I don't understand the question at all, especially not the example given.
If you have macChars[0] == 53, which is 0x35 in hex, then I would expect to get maxCharsHex[0] == '3' and macCharsHex[1] == '5' after the first char has been converted. This is done like so with sprintf():
sprintf(maxCharsHex, "%02x", (int) macChars[0] & 0xff);
The cast and mask is to be on the safe side for signed characters.
They are already converted, since character in C are represented by their corresponding character codes.
Therefore, as far as storing things in arrays is concerned there is nothing you need to do and if you want "5" and "B" to show up correctly when printing or doing something like that its a matter of using the correct printing function (putchar, printf with %c, etc).

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