I have a big problem with my function.
My program (C) is supposed to display the number of occurrences of a letter (Upper or lower case).
The program must handle 2 arguments and work as follows:
./rush2 “Just because I don’t care doesn’t mean I don’t understand!” a
4
I tried this :
#include <stdio.h>
int rush2(int argc, char **argv)
{
int i = 0;
int count_letter = 0;
while (argv[0][i] != '\0') {
if (argv[0][i] == argv[1][0]) {
count_letter = count_letter + 1;
}
i = i + 1;
}
printf("%d", count_letter);
return (count_letter);
}
int main (int ac, char **av)
{
rush2(ac, av);
return (0);
}
My function prints 0 or seg faults.
Please help me.
Try this:
#include <stdio.h>
void rush2(char str[], char c_lower)
{
char c_upper = c_lower - 32;
int i = 0;
int count_letter = 0;
while (str[i] != '\0')
{
if (str[i] == c_lower || str[i] == c_upper)
{
count_letter += 1;
}
i += 1;
}
printf("%d\n", count_letter);
}
int main (int argc, char *argv[])
{
rush2(argv[1], argv[2][0]);
return 0;
}
Related
i'm really stuck.
I pust a big part of code you can try to run it on in online c compiler. My problem is weird, every time after 2 iteration i lost the data on spliter[0][0] when i mean "lost" is modified, for better understand please look what is printing it.
Inside
Inside the loop that iterates I wanted to see if the characters were well allocated in the present time and this is the case, only afterwards when I want to check it is impossible for me to do anything.
My program boils down to separating one character string according to another and dynamically allocating these character strings in my split. Each separator character counts as separator.
I have already prepared the test in comment. I really need help, too long time im stuck here..
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int is_c(char c, char *cha) {
while (*cha) {
if (*cha == c) {
return (1);
}
cha++;
}
return (0);
}
int ct_str(char *str, char *cha) {
int sw;
int nbr;
char item;
nbr = 0;
while (*str) {
if (!(is_c(*str, cha)) && *str >= 33 && *str <= 127 && sw == 1) {
sw = 0;
nbr+=1;
}
str++;
while (is_c(*str, cha)) {
str++;
sw = 1;
}
}
return (nbr);
}
int no_blk(char *str, int position, char *cha) {
while (!is_c(str[position], cha)) {
if (str[position] >= 33 && str[position] <= 127)
return (1);
position++;
}
return (0);
}
int get_size(char *str, int position, char *cha) {
int item;
item = position;
int j;
j = 0;
while (str[item]) {
if (is_c(str[item], cha))
return (j);
item++;
j++;
}
return (0);
}
void split_this(char **split, char *str, char *cha) {
int i;
int level;
int sw;
int e;
level = 0;
i = 0;
int item = 0;
int element = 0;
while(str[i + 1]) {
e = 0;
while(is_c(str[i], cha)) {
sw = 1;
i++;
}
if(sw == 1 && (!is_c(str[i], cha)) && no_blk(str, i, cha)) {
split[level] = (char*)malloc(sizeof(char) * get_size(str, i, cha) + 1);
e = i;
//printf("%i \n", get_size(str, i, cha));
while(e - i < get_size(str, i, cha)) {
split[level][e - i] = str[e];
//printf("%c", split[level][e - i]);
split[level][(e + 1) - i] = '\0';
e++;
}
printf("%c", split[0][0]);
sw = 0;
level++;
}
i++;
}
free(split);
/*
int it = 0;
int ee;
while(split[it]) {
ee = 0;
while(split[it][ee]) {
printf("%c", split[it][ee]);
ee++;
}
it++;
}
*/
}
void ft_split(char *str, char *cha) {
char **spliter = NULL;
spliter = (char**)malloc(sizeof(char) * ct_str(str, cha) + 1);
split_this(spliter, str, cha);
}
int main(int argc, char **argv) {
//if (argc == 3)
//ft_split(argv[1], argv[2]);
ft_split("%%am%s%s%ss%%s%%%qsdqsd%%%on%vs%lre%" , "%%");
return (0);
}
I am new here and working on the second homework Caesar of cs50, it seems most of my review is correct except the last one -- I cannot handle the situation of lacking argv[1], which means if I only type ./caesar, it will return segmentation fault. I am wondering why this code if (argc != 2) cannot return 0 when argc == 1, however it works when argc > 1, I find that is weird. Can anyone help me?? Thanks in advance!
# include <stdio.h>
# include <cs50.h>
# include <string.h>
# include <ctype.h>
# include <math.h>
# include <stdlib.h>
int check_the_key(int argc, string y);
int main(int argc, string argv[])
{
string x = argv[1];
int y = argc;
int k = check_the_key(y, x);
if (k == 0)
{
printf("ERROR!!!!!\n");
return 1;
}
else
{
// printf("The key is %i\n", k);
string text = get_string("Input your text:");
int i;
int n;
printf("ciphertext: ");
for (i = 0, n = strlen(text); i < n; i++)
{
if (islower(text[i]))
{
printf("%c", (text[i] - 97 + k) % 26 + 97 );
}
else if (isupper(text[i]))
{
printf("%c", (text[i] - 65 + k) % 26 + 65);
}
else
{
printf("%c", text[i]);
}
}
printf("\n");
return 0;
}
}
int check_the_key(int argc, string y)
{
int number = argc;
string key = y;
int numberkey = atoi(key);
if (argc != 2)
{
return 0;
}
else
{
if (numberkey > 0)
{
return numberkey;
}
else
{
return 0;
}
}
}
I know what is going on! Because I need to pass some value into atoi(), if I only call ./caesar, there is no value I can pass into atoi(), so it causes segmentation fault. Which means I need to change code order slightly, put int numberkey = atoi(key); inside the else loop. So the code will run if (argc != 2) first, if no, then go to the next step! Here is the code after change.
int check_the_key(int argc, string y)
{
int number = argc;
string key = y;
if (argc != 2)
{
return 0;
}
else
{
int numberkey = atoi(key);
if (numberkey > 0)
{
return numberkey;
}
else
{
return 0;
}
}
}
I'm trying to figure out a way to only print out the characters without getting duplicates in C. Any help is appreciated.
For example, if i pass in 'Hello', i would like 'Helo' returned.
My current code that just prints out the passed in argument:
#include <stdio.h>
int main(int argc, char **argv)
{
int i;
i = 0;
while (argv[1][i] != '\0')
{
putchar(argv[1][i]);
i++;
}
return (0);
}
Edit: preferably without the use of any extra functions / #includes’s
You can try this. You need an array with the length of the max possible ascii code, to handle the seen characters. Hope this helps.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
int * seen = calloc(256, sizeof(char));
if (argv[1] == NULL) {
printf("No argument.\n");
return 0;
}
for (int i = 0 ; i < strlen(argv[1]) ; i++) {
if (seen[argv[1][i]] != 1) {
seen[argv[1][i]] = 1;
putchar(argv[1][i]);
}
}
free(seen);
}
You can do like this:
#include <stdio.h>
int main(int argc, char **argv)
{
int i;
char f[128];
unsigned char ch;
if (argc != 2) {
printf("use : ./a.out str");
return -1;
}
for (i = 0; i != sizeof(f); ++i)
f[i] = 0;
for (i = 0; argv[1][i] != '\0'; ++i) {
ch = argv[1][i];
if (f[ch] == 0) {
putchar(ch);
f[ch] = 1;
}
}
return 0;
}
#include <stdio.h>
int any(char s1[], char s2[]) {
//converts to lower case
int c = 'a';
int i1 = 0;
while (s1[i1] != '\0') {
if (s1[i1] >= 'A' && s1[i1] <= 'Z')
s1[i1] += 32;
++i1;
}
int i2 = 0;
while (s2[i2] != '\0') {
if (s2[i2] >= 'A' && s2[i2] <= 'Z')
s2[i2] += 32;
++i2;
}
i1 = 0;
while (s1[i1] != '\0') {
i2 = 0;
while (s2[i2] != '\0') {
if (s1[i1] == s2[i2])
return i1;
++i2;
}
++i1;
}
return -1;
}
main() {
//printf("test");
printf("%d", any("This is fun", "fin"));
}
This code causes a segmentation fault and I'm pretty sure it happens when I try to set one of the chars in the array equal to an int. How do I not get a seg fault?
You are calling any with pointers to string constants. Attempting to modify these strings invokes undefined behavior.
Also note that the prototype for main should be int main(void) or int main(int argc, char *argv[]), and main should return 0 for successful operation.
You are implementing a case insensitive version of a generalized version of strchr with multiple characters, but you should not modify the argument strings, and you should rely on the functions from <ctype.h> instead of assuming ASCII.
Here is a better version:
#include <ctype.h>
#include <stdio.h>
int any(const char s1[], const char s2[]) {
int i1 = 0;
while (s1[i1] != '\0') {
int i2 = 0;
while (s2[i2] != '\0') {
if (tolower((unsigned char)s1[i1]) == tolower((unsigned char)s2[i2]))
return i1;
++i2;
}
++i1;
}
return -1;
}
int main(void) {
//printf("test");
printf("%d", any("This is fun", "fin"));
return 0;
}
I am accepting a string as a command line argument. I want to check whether the inputted string is a palindrome or not and print the result. I have written the following code. But its displaying the result 'not palindrome' for all inputs.
#include<stdio.h>
#include<string.h>
int main(int argc, char argv[20]) {
int i;
int l = strlen(argv);
char str[20];
bzero(str, 20);
for(i=0; i<l; i++)
{
str[i] = argv[i+2];
}
int flag;
int len = strlen(str);
for(i=0; i< len/2; i++)
{
if(str[i] == str[len - (i+2)])
{
flag = 0;
}
else
{
flag = 1;
break;
}
}
if(flag == 0)
printf("Palindrome\n");
else
printf("Not a palindrome\n");
}
You could do it in a K&R-style by having two offset iterators in a for-loop:
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main(int argc, char *argv[]) {
assert(argc != 1);
char *text = argv[1];
int len = strlen(text);
int is_palindrome = 1;
int i, j;
for(i = 0, j = len - 1; i < len / 2; i++, j--) {
if(text[i] != text[j]) {
is_palindrome = 0;
break;
}
}
printf("%s a palindrome.\n", is_palindrome ? "is" : "isn't");
return(0);
}
Changes from original:
Changed shift(len >> 1) to division(len / 2) as tenfour suggested.
Updated based on comments:
int is_palindrome(const char *s)
{
const char *t = s + strlen(s);
while (s<t && *s==*--t) s++;
return s>=t;
}
And since the OP wants a version that's not so heavy on pointers:
int is_palindrome(const char *s)
{
size_t i=0, j = strlen(s);
while (i<j && s[i]==s[--j]) i++;
return i>=j;
}
For reference, here's the original buggy version:
int is_palindrome(const char *s)
{
const char *t = s + strlen(s) - 1;
while (s<t && *s++==*t--);
return s>=t;
}
For one thing, your signature for main is off. It should be int main(int argc, char** argv) or int main(int argc, char * argv[]). You're treating a pointer to a string as if it were a string.
When you've changed that, the string you want should be in argv[1] (since argv[0] is some representation of the program name).
There's a good case for using pointers rather than indexes for this:
int is_palindrome(const char *s) {
const char *end = s + strlen(s);
while (end > s) {
--end;
if (*end != *s) return 0;
++s;
}
return 1;
}
If you like short, confusing code, you can re-write that:
int is_palindrome(const char *s) {
const char *end = s + strlen(s);
while (end > s) if (*(--end) != *(s++)) return 0;
return 1;
}
argv isn't a string, it's an array of strings, one for the program name and then one for each argument (usually space-separated in a command line). So to test if the first argument is a palindrome, you're interested in argv[1].
int main(int argc, char **argv) {
if (argc != 2) {
printf("usage: %s <string>\n", argv[0]); // or something
return 1;
}
if (is_palindrome(argv[1])) {
printf("Palindrome\n");
} else {
printf("Not a Palindrome\n");
}
}
The first loop doesn't make sense.
Copying the string to another doesn't make sense.
Just do it and adjust the index:
#include<stdio.h>
#include<string.h>
int main(int argc, char **argv) {
int i;
char * str = argv[1];
int flag;
int len = strlen(str);
for(i=0; i< (len+1)/2; i++)
{
printf("DEBUG: Comparing %c %c\n",str[i], str[len - (i+1)]);
if(str[i] == str[len - (i+1)])
{
flag = 0;
}
else
{
flag = 1;
break;
}
}
if(flag == 0)
printf("Palindrome\n");
else
printf("Not a palindrome\n");
}
No pointers (except the one use for making a copy of the original string).
#include <stdio.h>
#include <string.h>
int main( int argc, char *argv[] )
{
char *s2;
if ( argc != 2 )
return ( 1 ); // not properly invoked
if ( (s2 = strdup( argv[1] )) == NULL )
return ( 2 ); // failed (not likely)
printf( "\"%s\" %s a palindrome.\n", argv[1], strcmp( argv[1], strrev( s2 ) ) ? "is not" : "is" );
free( s2 );
return ( 0 );
}