Comparing char in a string to another char in C - c

what I have is a string that I get from txt file.
fgets(num_string, lenght, file);
num_string = "011110110101"
So than I select the first number and display it:
printf("Number: %c", num_string[0]);
After that my program gets all the numbers in string with this loop and it should then check each number if its 0 or 1:
for(j=0; j<=11; j++){
printf("numbers: %c\n", num_string[j]);
if(strcmp(num_string[j], zero)==0){
num_of_zeros++;
printf("\nNum of zeros: %d", num_of_zeros);
}
else{
num_of_ones++;
printf("\nNum of ones: %d", num_of_ones);
}
}
But the if statement does not want to work. Here is the problem that it writes in terminal:
AOC_2021_day_3.c: In function 'main':
AOC_2021_day_3.c:27:27: warning: passing argument 1 of 'strcmp' makes pointer from integer without a cast [-Wint-conversion]
if(strcmp(num_string[j], zero)==0){
^~~~~~~~~~
In file included from AOC_2021_day_3.c:3:0:
c:\mingw\include\string.h:77:38: note: expected 'const char *' but argument is of type 'char'
_CRTIMP __cdecl __MINGW_NOTHROW int strcmp (const char *, const char *) __MINGW_ATTRIB_PURE;
^~~~~~
I would appreciate any help :D

strcmp is for comparing to cstrings. In this case, you do not need strcmp at all. You want to check whether a specific character inside num_string is 0 or not. The if(strcmp(num_string[j], zero)==0) statement can be replaced with if(num_string[j] == '0').

Related

C function to return greatest ascii value

I'm trying to create a C function to return a pointer to the char with the greatest ascii value in a string, but my function is returning 'H' instead of 'o'. I think it's something to do with the if statement in the for loop but I'm not sure what the problem is. Any help is appreciated. Thanks!
char * select_max(char str[]);
int main(void) {
printf("%c\n",select_max("Hello"));
printf("All tests passed successfully.\n");
}
char *select_max(char str[]){
int length = strlen(str);
if(length<1){//returns 0 if string length is less than one
printf("Invalid string.\n");
return 0;
}
char *max = str;
for(int i=0;i<length;i++){
if(str[i] > max){
max = str[i];
}
}
return *max;
}
Try adding a printout so that you can see your bug in action. For example, just before your if:
printf("%c > %c = %d\n", str[i], max, (str[i] > max));
I believe this will quickly reveal the bug. [Hint: there are 5 bugs in your program.]
Compiler is nice enough to give you quite useful warnings, you should follow them, read carefully and try to understand. It won't point out your logical errors but you can deduce these too in this case.
main.c: In function 'main':
main.c:4:5: warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration]
printf("%c\n",select_max("Hello"));
^~~~~~
main.c:4:5: warning: incompatible implicit declaration of built-in function 'printf'
main.c:4:5: note: include '<stdio.h>' or provide a declaration of 'printf'
main.c: In function 'select_max':
main.c:10:18: warning: implicit declaration of function 'strlen' [-Wimplicit-function-declaration]
int length = strlen(str);
^~~~~~
main.c:10:18: warning: incompatible implicit declaration of built-in function 'strlen'
main.c:10:18: note: include '<string.h>' or provide a declaration of 'strlen'
You first need to include the libraries that you use functions from, printf is from stdio.h and strlen is from string.h.
main.c:22:12: warning: returning 'char' from a function with return type 'char *' makes pointer from integer without a cast [-Wint-conversion]
return *max;
^~~~
You appear to be confusing chars with char*s. Since select_max is logically supposed to return just a character, (and you are already returning a char) declaring it as below will suffice.
#include<stdio.h>
#include<string.h>
char select_max( char str[] );
main.c:19:17: warning: assignment to 'char *' from 'char' makes pointer from integer without a cast [-Wint-conversion]
max = str[i];
And in the implementation of select_max, there is a similar problem. The temporary variable to hold the highest character is of type char* where it just needs to be a char:
char select_max(char str[]){
// ^___
int length = strlen(str);
if(length<1){//returns 0 if string length is less than one
printf("Invalid string.\n");
return 0;
}
// Initialize it to 0, has to be lower than any ASCII letters in order your algorithm to work. DO NOT leave it uninitialized.
char max = 0; // <---
for(int i=0;i<length;i++){
if(str[i] > max){
max = str[i];
}
}
return max;
}
The code above defines max as a char and initializes it to 0. Assigning str to it was pointless anyway. You are iterating through your string one character at a time and storing the character in a temporary container.
Note that the code in the for loop had already written as if it was of type char.
The same algorithm of course can be implemented in various ways but I suppose this was what you were trying to do.

Passing Argument 1 makes integer from pointer without a cast warning for putchar

I'm studying an exercise of making a simple code that has the function that acts the same way as printf using a variadic function.
Also, I wish to use sprintf and putchar, and not printf.
The code seems to act and give the results as it should do (i.e print a character for %c, and an integer for %d).
However, I keep getting a warning message for putchar(cStr); that says Passing Argument 1 of 'putchar' makes integer from pointer without a cast.
Also, I get a note that says expected int but argument is of type char *.
I've tried to get this solved by changing putchar(cStr); into putchar(*cStr);, but then the code gives me a segment fault.
What should I do to get the warning message and note solved?
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
void new_printf(const char*format, ...);
int main(void)
{
new_printf("A single character : %c An integer : %d \n", 'T', 37);
return 0;
}
void new_printf(const char *format, ...)
{
va_list ap;
char ary[50];
char *cStr;
int iNum, i=0;
va_start(ap, format);
while(*format)
{
if(strncmp(format, "%d",2) == 0){
iNum = va_arg(ap, int);
sprintf(ary, "%d", iNum);
while(ary[i]!='\0'){
putchar(ary[i]);
i++;
}
format = format + 2;
}
else if(strncmp(format, "%c", 2)==0)
{
cStr = va_arg(ap, char*);
putchar(cStr);
format = format + 2;
}
else{
putchar(*format);
format++;
}
}
va_end(ap);
}
The correct results would be as follows:
A single character : T An integer : 37
In the call new_printf("A single character : %c An integer : %d \n", 'T', 37);, 'T' is passed for the %c conversion. 'T' is a character: It is a small integer value. It is not a pointer. For historic reasons, its type is int. This is a correct thing to pass for %c.
Under else if(strncmp(format, "%c", 2)==0), in cStr = va_arg(ap, char*);, you tell va_arg to give you the next argument and that that argument is a char *. It is not. It is an int.
You should retrieve it with va_arg as an int and assign it to an int, not to char *, or simply use it directly as an int.
You should use int x = va_arg(ap, int); putchar(x); or simply putchar(va_arg(ap, int));.

How to print the days of the week using a structure member?

I want to print the days of the week in this program but it doesn't work, what can I do to fix it ?
#include<stdio.h>
struct month{
int date[12];
char day[7];
}mon;
main()
{ int i;
strcpy(mon.day[0],"Sunday");
strcpy(mon.day[1],"Monday");
strcpy(mon.day[2],"Tuesday");
strcpy(mon.day[3],"Wednesday");
strcpy(mon.day[4],"Thursday");
strcpy(mon.day[5],"Friday");
strcpy(mon.day[6],"Saturday");
for(i=0;i<7;i++)
{
printf("Day %d is %c\n",i+1,mon.day[i]);
}
}
You are trying to store strings in char. However, a string is an array of char. Instead of this:
char day[7];
You need something such as:
char day[7][16];
Now you have 16 char to fit in a weekday, and you have that seven times, one for each day. Also, your print is wrong. To print strings, you need %s, not %c. %c is just for one single char:
printf("Day %d is %s\n", i + 1, mon.day[i]);
Another way of doing it is to have an array of char* instead of char and only storing the address of the strings rather than copying the strings:
char *day[7];
Then store the addresses like this:
mon.day[0] = "Sunday";
mon.day[1] = "Monday";
mon.day[2] = "Tuesday";
...
And print it the same way, with %s.
If you try to compile your program, your compiler will give you certain warnings. Like
Problem 1:
source_file.c:10:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
main()
^
The proper signature of main() is int main(void), for usual hosted environments.
Problem 2:
source_file.c: In function ‘main’:
source_file.c:13:5: warning: implicit declaration of function ‘strcpy’ [-Wimplicit-function-declaration]
strcpy(mon.day[0],"Sunday");
^
source_file.c:13:5: warning: incompatible implicit declaration of built-in function ‘strcpy’
source_file.c:13:5: note: include ‘<string.h>’ or provide a declaration of ‘strcpy’
You'd need to include string.h header file which contains the declaration for strcpy().
Problem 3:
source_file.c:13:12: warning: passing argument 1 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
strcpy(mon.day[0],"Sunday");
This indicates, the first argument of strcpy() expects a char *, but you're passing a char, casted to an int.
This is the most important point here, as you'd see, you need to pass a buffer which can contain the content from the copied string. Thu's, you'd need
day to be a 2-D array
use day[i] to store the content
use %s to print the content thereof.
For constants like day and month, better constructed like the following, unless you are practicing with struct.
#include<stdio.h>
int main()
{
const char *day[] = {"Sunday", "Monday", "Tuesday","Wednesday", "Thursday", "Friday", "Saturday" };
//^^^^^ array of strings.
for(int i=0;i<7;i++)
printf("Day %d is %s\n",i+1,day[i]);
return 0;
}

va_arg with wide char in c, how to handle %S

I'm trying to implement my own printf, I have an issue handling wide char %S.
void my_printf(char *format, ...)
{
char *traverse;
va_list arg;
va_start(arg, format);
traverse = format;
while (*traverse)
{
if (*traverse == '%')
{
*traverse++;
if (*traverse == 'S')
printf("%S\n", va_arg(arg, wchar_t));
*traverse++;
}
else
putchar(*traverse++);
}
va_end(arg);
}
warning: format specifies type 'wchar_t *' (aka 'int *') but the argument has type 'wchar_t' (aka 'int') [-Wformat]
printf("%S\n", va_arg(arg, wchar_t));
when I use following code printf works fine.
printf("%S\n", L"Some String");
You're passing a pointer and retrieving an integer. The types of L"Some String" and va_arg(arg, wchar_t), do not match.
Retrieve a pointer instead:
va_arg(arg, wchar_t*)
The line *traverse++; is not correct, the dereference is redundant. It should be simply: traverse++;
On a side note, your code doesn't do any input checking and a malicious string will cause undefined behavior. This will happen if the character '%' is the last character, the iterator traverse will point to one beyond the last element in the array and the check while (*traverse) will dereference it.

Counting words from argument in C

I'm new to C and I try to make a program counting words in a sentence given as arguments when running the program. A word is a character or several seperated by either: ' ', '\n', ',' or '.'. Example: ./words abc abc = 2 words
But I keep getting: "segementation fault(core dumped)". Following is code:
int main(char **argv)
{
char buf[80];
sprintf(buf,"%d words\n",words(argv));
write(1,buf,strlen(buf));
return 0;
}
int words(char **argv)
{
int i=0, sum=0;
while(argv[i] != '\0')
{
if(argv[i] == '.' || argv[i] == ',' || argv[i] == ' ' || argv[i] == '\n')
sum++;
i++;
}
}
Argv is a **char or a pointer to an array of strings. Your code is treating it as if it is a single string so is looping through the pointers to strings and counting them. As none of these pointers is null the program continues beyond the end of the array causing a segfault.
me.c:2:5: warning: first argument of âmainâ should be âintâ [-Wmain]
me.c:2:5: warning: âmainâ takes only zero or two arguments [-Wmain]
me.c: In function âmainâ:
me.c:4:1: warning: implicit declaration of function âwordsâ [-Wimplicit-function-declaration]
me.c:5:1: warning: implicit declaration of function âwriteâ [-Wimplicit-function-declaration]
me.c:5:1: warning: implicit declaration of function âstrlenâ [-Wimplicit-function-declaration]
me.c:5:13: warning: incompatible implicit declaration of built-in function âstrlenâ [enabled by default]
me.c: In function âwordsâ:
me.c:11:16: warning: comparison between pointer and integer [enabled by default]
me.c:11:33: warning: comparison between pointer and integer [enabled by default]
me.c:11:51: warning: comparison between pointer and integer [enabled by default]
me.c:11:69: warning: comparison between pointer and integer [enabled by default]
gcc -Wall filename.c will produces all of the above warnings
These are the warnings in your code. Avoid all. and then try.
Please found Answers for these By searching on google
how to use command line arguments
how to declare a function
how to compare strings and how '.' is differ from "."
If I am not mistaken, then the arguments are automatically split into separate character strings. This is why you get a pointer to a pointer (e.g char ** instead of char*). You are dereferencing the argv array only once. Try this:
while(argv[i] != NULL) {
i++;
}
Second, you wont be able to detect newlines that way, since by definition you cannot pass newline in the arguments. What you probably want to do is parse the input from stdin and invoke your program like this:
echo "abc abc" | ./words
or
./words < SOME_TEXT_FILE
Last but not least your words function does not return anything, it needs to return i:
int words(char** argv) {
//...
return i;
}
That is probably the reason why your program segfaults, since the return value of words() will be NULL and then sprintf will try to dereference the result of the function.
So the whole function needs to look somewhat like this:
int words(char** argv) {
int counter = 0;
while(char[i] != NULL) {
int j = 0;
while(char[i][j] != '\0') {
if(char[i][j] == '.') { //no need to check for '\n'...
counter++;
}
j++;
}
i++;
counter++;
}
return counter;
}
1. Iterate over argv.(having in mind that argv[i] is a pointer to char, argv[0] holds name of the program being executed, and last element of argv is NULL pointer.
2. use strtok function from string.h library to split argv[i] with " .,\n". (every time strtok returns non-NULL value you increment words count).
With some reading on command line arguments and strtok you can easily make it work with any arguments passed.

Resources