compare two numbers in c using char and strcmp - c

I am trying to compare two set of data using strcmp. This first set of data are var1 which is get from fgets(var1, 100, stdin). The second set of data are generate randomly by rand. When I complie it, I get two same errors. They both come from char f.
warning: assignment makes pointer from integer without a cast printf(f);
warning:assignment makes pointer from integer without a cast if (strcmp(var1,f)==0)
i already declare the randomly generated number char f = rand() % 38; in char, why will it not work?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main()
{
char var1[100];
int result;
fgets(var1, 100, stdin);
srand(time(NULL));
char myArray[38] = { 1,5,3,4};
char f = rand() % 38;
printf(var1);
printf(f);
if (strcmp(var1,f)==0) {
result = 1;
printf("It work\n");
}
else {
printf("It didn't work!\n");
result = 0;
}
return 0;
}
EDITED CODE
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main()
{
char var1[100];
int result;
scanf("%s",var1);
srand(time(NULL));
char myArray[7] = { 0,28,9,26,30,11,7 };
int randomindex= 1 + (rand() % 100);
char f = myArray[randomindex];
char str_f[2] = { f, '\0' };
printf("var1: %s\n",var1);
printf("%s",str_f);
printf("\n");
if (strcmp(var1,str_f)==0) {
result = 1;
printf("It work\n");
}
else {
printf("It didn't work!\n");
result = 0;
}
return 0;
}

As commented above, in C Langage, functions from Library have a strict format and using not that expected format will occur warning or error at compilation time or runtime.
Function 1 - the printf() is the common function to write C strings to the standard output stdout (declared in <stdio.h>).
See the C library function - printf()
int printf(const char *format, ...)
In the provided source code, the printf() function has been used in the following cases:
printf("It work\n"); to write a fixed string which complies with the const char * expected format of the first parameter ==> OK,
printf(var1); to write the content of the entered string var1 (declared as char var1[100];) which not exactly complies with const char * of the first parameter but will be cast during compile time. A proposed format to write the var1 string could be printf("%s",var1); (or more verbose printf("var1: %s",var1);) where the first parameter "%s" will specify that the following argument var1 will be a string.
printf(f); to write the content of the random value (declared as char f;) which doesn't comply with const char * of the first parameter and doesn't compile at all. The minimal expected format to write the f character is printf("%c",f); (or more verbose printf("f=%c",f);) where the first parameter "%c" will specify that the following argument f will be a character.
Function 2 - the strcmp() is a function to compare two C strings parameters (declared in <string.h>.
See the C library function - strcmp()
int strcmp(const char *str1, const char *str2)
In the provided source code, the strcmp() function has not been used as specified. The function expects two input parameters:
First parameter of strcmp(var1,...)==0 is var1 (declared as char var1[100];) which not exactly complies with const char * but will be cast during compile time.
Second parameter of strcmp(...,f)==0 is f (declared as char f;) which doesn't comply with const char * and doesn't compile at all.
To compare the character f with var1, it shall be necessary to
convert it to a string (In C, a string is an array of char ended by
a character).
Solution 1 - how to convert the character char f; to a string.
A C string is an array of characters: char str_f[]= { '<char>', ... , '<NUL>' };. Meaning that a minimal array of 2 characters is necessary to convert the character char f; to a string.
char f = rand() % 38;
// use a 2 characters string
char str_f[2] = { f, '\0' };
// Could be also initialised as str_f[0] = f; str_f[1] = '\0';
// compare the strings using `str_f`
if (strcmp(var1,str_f)==0) {
Warning 1 - be careful to the random value range.
When printing characters, a C string is supposed to be filled by ASCII
characters different from which is used to end the string.
In the provided source code, the assignment of f, char f = rand() % 38;, will generate values from 0 to 37 which include the character and the first 31 non-printable characters (ctrl-characters). Only characters greater than 31 will be displayed.
In will be more easy to generate: char f = ' ' + (rand() % 38);
where ' ' is the first printable ASCII character = 32.

Related

main() not reading multiple arguments [duplicate]

This question already has answers here:
What does int argc, char *argv[] mean?
(12 answers)
Closed 1 year ago.
I am writing a code for a Caeser cipher program in C. the code is working as intended however I was trying to edit the code to make it accept multiple arguments instead of just one like it does currently. To incorporate this I added a new array in the main() named argvalue1 to hold the second argument. Furthermore I added a second interating variable and another loop to read the characters from the second array. I am still really new to using C, just not sure why the program will not read the second argument and how I can fix that.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// Compile this program with:
// cc -std=c11 -Wall -Werror -o rotate rotate.c
#define ROT 13
// The rotate function returns the character ROT positions further along the
// alphabetic character sequence from c, or c if c is not lower-case
char rotate(char c)
{
// Check if c is lower-case or not
if(islower(c)) {
// The ciphered character is ROT positions beyond c,
// allowing for wrap-around
return ('a' + (c - 'a' + ROT) % 26);
}
else {
return c;
}
}
// Execution of the whole program begins at the main function
int main(int argcount, char *argvalue[], char *argvalue1[])
{
// Exit with an error if the number of arguments (including
// the name of the executable) is not precisely 2
if(argcount != 3) {
fprintf(stderr, "%s: program expected 1 argument, but instead received %d\n",
argvalue[0], argcount-1);
exit(EXIT_FAILURE);
}
else {
// Define a variable for a later loop
int i;
int j;
// Calculate the length of the first argument
int length = strlen(argvalue[1]);
int length2 = strlen(argvalue1[1]);
// Loop for every character in the text
for(i = 0; i < length; i++) {
// Determine and print the ciphered character
printf("%c", rotate(argvalue[1][i]));
printf("%c", rotate(argvalue1[1][j]));
}
// Print one final new-line character
printf("\n");
// Exit indicating success
exit(EXIT_SUCCESS);
}
return 0;
}
You don't need to add char *argvalue1[] at all here. Notice that the the second argument char *argvalue[] is actually an array.
The second argument that you run your code with will be part of this array and that is how you should access it within your code.
To reiterate :
argvalue[0] --> first argument
argvalue[1] -- second argument

How to separate character and number from string in c program

For example, I want to separate the string "0013subdivision" into 0013 (as an integer that can do addition, subtraction, etc. not char) and subdivision (as a char itself) in the given string.
This is my code so far:
#include <stdio.h>
#include <stdlib.h>
char location[10]; /* for the input with number and letter */
char x;
int house[10]; /* for the integer that will be separated from the string */
int main()
{
printf("Input: ");
scanf ("%s", &location[x]);
x=0
for (x=0; location[x]!='\0'; x++ );
return 0;
}
Based on my research, the code atoi is used to convert the converted value back to int (if I'm not mistaken) but I don't know when to place the function.
location is char array, if you are reading as string use only %s with string name only, index not required.
scanf ("%s", &location[x]); --> scanf ("%s", location);
After separating only int from char array you need to store one int value into house.
int house[10] --> int house.
Here is the code for extracting only int from string :
char location[10]; /* for the input with number and letter */
int x;
int house = 0 ; /* for the integer that will be separated from the string */
int main()
{
printf("Input: ");
//scanf ("%s", &location[x]);
scanf ("%s", location);
for (x=0; location[x]!='\0'; x++ ) {
if(location[x]>='0' && location[x]<='9') {
house =(house * 10) + (location[x]-48);
}
}
printf("int part = %d \n",house);
return 0;
}
The main problem in the code is
scanf ("%s", &location[x]);
Where you did not impose any limit on the scanning. An input like 0013subdivision will cause out of bound memory access leading to undefined behavior.
Always limit the input size with the length modifier, like, for an array defined as
char location[10]
use the conversion specification like
scanf ("%9s", location); // (i) one element saved for terminating null
// (ii) the array name decays to the pointer to 1st element
//in case of an argument to a function call.
Then, you don't need an integer array to store the extracted integer. A singular variable would suffice.
However, i'd like to suggest a much robust way:
read the user input using fgets()
then, scan the input using sscanf() and appropriate conversion specifier, like %4d%9s or alike.
The most correct way to do this is to use the strto... family of functions from stdlib.h. For example:
printf("%ld\n", strtol(str, NULL, 10));
The atoi family of functions should never be used for any purpose, since they have broken error handling and can be 100% replaced by the strto... functions.
You could use the scanf family of functions but they are needlessly slow and notoriously dangerous, so I don't really see the point of using them here.
If you are interested in implementing the actual copying manually, for learning purposes, it is fairly trivial:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main (void)
{
const char str[] = "0013subdivision";
char number_part [sizeof(str)];
char letter_part [sizeof(str)];
size_t i;
for(i=0; str[i]!='\0' && isdigit(str[i]); i++) // find where the letters start
{}
memcpy(number_part, &str[0], i); // copy digit part
number_part[i] = '\0'; // append null terminator
memcpy(letter_part, &str[i], sizeof(str)-i); // copy letter part + null term
puts(number_part);
puts(letter_part);
printf("%ld\n", strtol(str, NULL, 10));
}
If the string is a run-time variable, you have to use strlen(str)+1 instead of sizeof().
strtol converts string to number and also gives you back the character it stopped on, i.e. first character after number.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char* const input = "0013subdivision";
const char* string;
const long number = strtol(input, &string, 10);
printf("Number: %ld String: '%s'\n", number, string);
// Number: 13 String: 'subdivision'
return 0;
}
https://repl.it/repls/SphericalImpracticalTinamou

How do you convert parameters from char to int in the main function for C?

I have this code:
int main(int argc, char *argv[]) {
int num = *argv[1];
When I run the function in terminal with a parameter: for example, if I were to call ./main 17, I want num = 17. However, with this code, num = 49 (ASCII value for 1 because argv is an array of characters). How would I get it to read num = 17 as an int? Playing around with the code, I can get it to convert the parameter into an int, but it will still only read/convert the first value (1 instead of 17).
I'm new to C and the concept of pointers/pointers to arrays is still confusing to me. Shouldn't *argv[1] return the value of the second char in the array? Why does it read the first value of the second char in the array instead?
Thanks for help!
How do you convert parameters from char to int?
Can be done by a simple cast (promotion), but this isn't your case.
In your case *argv[] is array of pointer to char (You can use this for breaking down complex C declarations), meaning that argv[1] is the 2nd element in the array, i.e. the 2nd char* in the array, meaning *argv[1] is the first char in the 2nd char* in the array.
To show it more clearly, assume argv holds 2 string {"good", "day"}. argv[1] is "day" and *argv[1] is 'd' (note the difference in types - char vs char*!)
Now, you are left with the 1st char in your input string i.e. '1'. Its ascii is indeed 49 as, so in order to get it's "int" value you should use atoi like this:
int i = atoi("17");
BUT atoi gets const char * so providing it with 17 is a good idea while sending it a char would not. This means atoi should get argv[1] instead of *argv[1]
int main(int argc, char *argv[]) {
int num = atoi(argv[1]);
// not : int num = *argv[1]; --> simple promotion that would take the ascii value of '1' :(
// and not: int num = atoi(*argv[1]); --> argument is char
note: atoi is considered obsolete so you may want to use long int strtol(const char *str, char **endptr, int base) but for a simple example I preferred using atoi
Shouldn't *argv[1] return the value of the second char in the array?
Look at the signature:
int main(int argc, char *argv[])
Here, argv is an array ([]) of pointers (*) to char. So argv[1] is the second pointer in this array. It points to the first argument given at the command line. argv[0] is reserved for the name of the program itself. Although this can also be any string, the name of the program is put there by convention (shells do this).
If you just dereference a pointer, you get the value it points to, so *argv[1] will give you the first character of the first argument. You could write it as argv[1][0], they're equivalent. To get the second character of the first argument, you'd write argv[1][1].
An important thing to note here is that you can never pass an array to a function in C. The signature above shows an array type, but C automatically adjusts array types to pointer types in function declarations. This results in the following declaration:
int main(int argc, char **argv)
The indexing operator ([]) in C works in terms of pointer arithmetics: a[x] is equivalent to *(a+x). The identifier of an array is evaluated as a pointer to the first array element in most contexts (exceptions include the sizeof operator). Therefore indexing works the same, no matter whether a is an array or a pointer. That's why you can treat argv very similar to an array.
Addressing your "core" problem: You will always have strings in argv and you want numeric input, this means you have to convert a string to a number. There are already functions doing this. A very simple one is atoi(), you can use it like this:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc != 2)
{
// use program name in argv[0] for error message:
fprintf(stderr, "Usage: %s [number]\n", argv[0]);
return EXIT_FAILURE;
}
int i = atoi(argv[1]);
printf("Argument is %d.\n", i);
return EXIT_SUCCESS;
}
This will give you 0 if the argument couldn't be parsed as a number and some indeterminate value if it overflows your int. In cases where you have to make sure the argument is a valid integer, you could use strtol() instead (note it converts to long, not int, and it can handle different bases, so we have to pass 10 for decimal):
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char **argv)
{
if (argc != 2)
{
// use program name in argv[0] for error message:
fprintf(stderr, "Usage: %s [number]\n", argv[0]);
return EXIT_FAILURE;
}
errno = 0; // reset error number
char *endptr; // this will point to the first character not read by strtol
long i = strtol(argv[1], &endptr, 10);
if (errno == ERANGE)
{
fprintf(stderr, "This number is too small or too large.\n");
return EXIT_FAILURE;
}
else if (endptr == argv[1])
{
// no character was converted. This also catches the case of an empty argument
fprintf(stderr, "The argument was not a number.\n");
return EXIT_FAILURE;
}
else if (*endptr)
{
// endptr doesn't point to NUL, so there were characters not converted
fprintf(stderr, "Unexpected characters in number.\n");
return EXIT_FAILURE;
}
printf("You entered %ld.\n", i);
return EXIT_SUCCESS;
}
I'm new to C and the concept of pointers/pointers to arrays is still confusing to me.
In C strings are represented by null terminated ('\0') character arrays. Let's consider the following example:
char str[] = "Hello world!"
The characters would lie contiguous in memory and the usage of str would decay to a character pointer (char*) that points to the first element of the string. The address of (&) the first element taken by &str[0] would also point to that address:
| . | . | . | H | e | l | l | o | | W | o | r | l | d | ! | \0 | . | . | . |
^ ^
str null terminator
Shouldn't *argv[1] return the value of the second char in the array?
First of all in the argv is an array of character pointer char* argv[], so that it could be interpreted like an array of strings.
The first string argv[0] is the program name of the program itself and after that the arguments that are passed are coming:
argv[0] contains a pointer to the string: "program name"
argv[1] contains a pointer to the argument: "17"
If you dereference argv[1] with the use of * you get the first character at that address, here 1 which is 49 decimal in the Ascii code. Example:
p r ("program name")
^ ^
argv[0] (argv[0] + 1)
--------------------------------------------
1 7 ("17")
^ ^
argv[1] (argv[1] + 1)
How would I get it to read num = 17 as an int?
Check the number of passed arguments with argc which contains also the program name as one (read here more about argc and argv). If there are 2 you can use strtol() to convert argv[1] to the an integer. Use strtol() over atoi() because atoi() is considered to be deprecated because there is no error checking available. If atoi() fails it simply returns 0 as integer instead of strtol() that is setting the second argument and the global errno variable to a specific value.
The followig code will use the pointer that strtol() set the second argument to, to check for conversion errors. There are also overflow and underflow errors to check like it's described here on SO. Moreover you have to check if the returned long value would fit into an int variable if you want to store it into an int variable. But for simplicity I've left that out:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[])
{
/* At least 1 argument passed? */
if (argc >= 2)
{
char* endptr;
long num = strtol(argv[1], &endptr, 10);
/* Were characters consumed? */
if (argv[1] != endptr)
{
printf("Entered number: %ld\n", num);
}
else
{
printf("Entered argument was not a number!\n");
}
}
else
{
printf("Usage: %s [number]!\n", argv[0]);
}
return 0;
}
Here's what you want to do:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv []) {
int num = atoi (argv[1]);
printf ("Here's what you gave me: %d", num);
return 0;
}
Here's the documentation for atoi ().
argv is an array of strings, so argv[x] points to a string. atoi () accepts an ASCII string as input and returns an int.
Bonus: This is still a bit unsafe. Try running this program without passing it a parameter and see what happens.
Also, you must take a look at the documentation for strtol (), which is a safe way of doing this.

Extract an integer value from array and program without showing printf function

I want to extract a number from an array I introduce in the keyboard and convert it into one integer. My code is:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
int r, t, i;
char expressio[t];
char vector[50];
char rpn[t][4];
printf("Introduce the expresssion");
fgets(expressio, t, stdin);
t = strlen(expressio);
for (i = 0; i <= t; i++) {
if (isdigit(expressio[i])) {
r = atoi(expressio[i]);
vector[i] = rpn[0][r];
}
return 0;
}
}
I have this warning:
passing argument 1 of 'atoi' makes pointer from integer without a cast
How can i solve it?
Also, when I execute this program, it does nothing and it doesn't even print the "Introduce the expression". Why is this happening?
That warning means that you are passing a bad argument to the function. "atoi" is expecting an array of chars as argument, but you are passing a single char as argument here:
r = atoi(expressio[i]);
If you want to convert a single char into a number, you can do:
r = expressio[i] - '0';
If you look at the ascii table, you will notice that the ascii value of 0 is 48. If you substract 48 (or, like i did, the ascii value of 0) to your char expressio[i], you will get the corresponding number as an integer. Like this, if expressio[i] equals '8', then r will equal 8.

How to get the binary presentation in hex value of a char

Given a char, how to convert this char to a two digit char, which is the hex value of the binary presentation?
For example, given a char, it has a binary presentation, which is one byte, for example, 01010100, which is 0x54.....I need the char array of 54.
Actually it would be:
char c = 84;
char result[3];
sprintf(result,"%02x",c);
This is all far to easy readable :-)
#define H(x) '0' + (x) + ((x)>9) * 7
char c = 84;
char result[3] = { H(c>>4), H(c&15) };
The following code, using snprintf() should work:
#include <stdio.h>
#include <string.h>
int main()
{
char myChar = 'A'; // A = 0x41 = 65
char myHex[3];
snprintf(myHex, 2 "%02x", myChar);
// Print the contents of myHex
printf("myHex = %s\n", myHex);
}
snprintf() is a function that works like printf(), except that it fills a char array with maximum N characters. The syntax of snprintf() is:
int snprintf(char *str, size_t size, const char *format, ...)
Where str is the string to "sprint" to, size is the maximum number of characters to write (in our case, 2), and the rest is like the normal printf()

Resources