choosing between function returns - c

I have written a function which has two different options of what to return:
//function to compare the strings in function3
int compare(char* str, char* dest){
int answer;
int i;
int length;
length = strlen(str);
// int jlength;
// jlength = strlen(dest);
for(i=0; i<length; i++){
if(str[i] == dest[i]){
answer = 1;
}else {
answer = 2;
}
}
return answer;
}
I want to use this function later, and have different things happen depending on what the function has returned. Below are the relevant parts of how I have constructed that:
//compare the reversed str with the orignal, now stored in dest
compare(str, dest);
int function3answer;
if(compare == 1){
function3answer = 1;
}else{
function3answer = 2;
}
return function3answer;
}
When I compile I get the error:
warning: comparison between pointer and integer [enabled by default]
Adding single quotes around the 1 does not help (and also isn't really what I want because I am not referencing part of an array) nor does taking it down to one equals sign (this produces a different warning).
Thanks so much!

The error
warning: comparison between pointer and integer [enabled by default]
Comes from this line:
if(compare == 1){
You try to compare a function to an integer.
To get rid of this error, change the function using compare:
void some_function(...) {
//compare the reversed str with the orignal, now stored in dest
int compare_result = compare(str, dest);
int function3answer;
if(compare_result == 1){
function3answer = 1;
}else{
function3answer = 2;
}
return function3answer;
}
Now, the compare function. The way you implement it won't work as you expect:
If you compare "abc" and "poc", you will have in for loop:
i = 0, str[0] == 'a', dest[0] == 'p' ==> answer = 2
i = 1, str[0] == 'b', dest[0] == 'o' ==> answer = 2
i = 2, str[0] == 'c', dest[0] == 'c' ==> answer = 1
i = 3, going out for loop and returning **1**.
Worst, if you compare "a long string" with "tiny", you will get an UB when i is 4.
You could correct the compare function this way:
#define STRING_IDENTICAL 1
#define STRING_DIFFERENT 2
//function to compare the strings in function3
int compare(char* str, char* dest)
{
int answer;
int i;
int length;
length = strlen(str);
int jlength;
jlength = strlen(dest);
if (length != jlength)
{
/* since size are differents, string are differents */
return STRING_DIFFERENT;
}
for(i=0; i<length; i++){
if(str[i] != dest[i]){
/* at least one different character, string are differents */
return STRING_DIFFERENT;
}
}
/* if we reach this point, that means that string are identical */
return STRING_IDENTICAL;
}

Related

Counting # of index of undefined char array in C

I'm trying to count the number of indexes of an undefined char array which is used as a parameter in the function.
I am already aware that if my array was fixed I can use "sizeof", which isn't the case here.
Attempt:
int counting(char *name3) {
int count = 0;
int i;
//I have no idea what to put as my condition nor do I believe
//I am approaching this situation correctly...
for (i = 0; i < sizeof(name3); i++) {
if (name3[i] != '\0') {
count++;
}
}
return count;
}
Then if it is run by the following code
int main(void) {
char *name = "Lovely";
int x = counting(name);
printf ("The value of x = %d", x);
Prints: The value of x = 0
Any help or pointers would be amazing. Thank you in advance.
In C, Every string ends with '\0' (Null Character)
You can iterate until you meet the Null Character
The example code would be like this
char* name = "Some Name";
int len = 0;
while (name[len] != '\0') {
len++;
}
Also, if it is a char pointer, not char array, sizeof(char*) will always return 4 in 32-bit application and return 8 in 64-bit application (the size of the 'pointer' itself - the memory address size)
#include <stdio.h>
int main()
{
int i=0;
char *name = "pritesh";
for(i=0;;i++)
{
if(name[i] == '\0')
{
break;
}
}
printf("%d", i);
return 0;
}
This should work
note: this might be syntactically incorrect as I have not had my hands on c since a long time

Parse string to number in C

I tried to write a function to convert a string to an int:
int convert(char *str, int *n){
int i;
if (str == NULL) return 0;
for (i = 0; i < strlen(str); i++)
if ((isdigit(*(str+i))) == 0) return 0;
*n = *str;
return 1;
}
So what's wrong with my code?
*n = *str means:
Set the 4 bytes of memory that n points to, to the 1 byte of memory that str points to. This is perfectly fine but it's probably not your intention.
Why are you trying to convert a char* to an int* in the first place? If you literally just need to do a conversion and make the compiler happy, you can just do int *foo = (int*)bar where bar is the char*.
Sorry, I don't have the reputation to make this a comment.
The function definitely does not perform as intended.
Here are some issues:
you should include <ctype.h> for isdigit() to be properly defined.
isdigit(*(str+i)) has undefined behavior if str contains negative char values. You should cast the argument:
isdigit((unsigned char)str[i])
the function returns 0 if there is any non digit character in the string. What about "-1" and "+2"? atoi and strtol are more lenient with non digit characters, they skip initial white space, process an optional sign and subsequent digits, stopping at the first non digit.
the test for (i = 0; i < strlen(str); i++) is very inefficient: strlen may be invoked for each character in the string, with O(N2) time complexity. Use this instead:
for (i = 0; str[i] != '\0'; i++)
*n = *str does not convert the number represented by the digits in str, it merely stores the value of the first character into n, for example '0' will convert to 48 on ASCII systems. You should instead process every digit in the string, multiplying the value converted so far by 10 and adding the value represented by the digit with str[i] - '0'.
Here is a corrected version with your restrictive semantics:
int convert(const char *str, int *n) {
int value = 0;
if (str == NULL)
return 0;
while (*str) {
if (isdigit((unsigned char)*str)) {
value = value * 10 + *str++ - '0';
} else {
return 0;
}
}
*n = value;
return 1;
}
conversion of char* pointer to int*
#include
main()
{
char c ,*cc;
int i, *ii;
float f,*ff;
c = 'A'; /* ascii value of A gets
stored in c */
i=25;
f=3.14;
cc =&c;
ii=&i;
ff=&f;
printf("\n Address contained
in cc =%u",cc);
printf("\n Address contained
in ii =%u",ii);
printf(:\n Address contained
in ff=%u",ff);
printf(\n value of c= %c",
*cc);
printf(\n value of i=%d",
**ii);
printf(\n value of f=%f",
**ff);
}

C append chars into char array one by one

I have made up a function which returns some chars , all I want to do is to append all those returned chars into one string .
#include <stdio.h>
#include <string.h>
char func(int n);
int main()
{
int i;
char str[] = "";
size_t p = strlen(str);
for (i =0 ; i < 5; i++){
str[p++] = func(i);
str[p] = '\0';
p++;
}
printf("%s",str);
return 0;
}
char func(int n){
if (n == 0)
return '1';
if (n == 1)
return '2';
if (n > 1)
return '3';
}
//EDIT Output for this is 19
char func(n){
if (n == 0)
return '1';
if (n == 1)
return '2';
if (n > 1)
return '3';
}
You should always specify the type for variables.
Please use something like int n instead of just n.
It's also bad that all of your returns are conditional, it's better to have a return statement that's guaranteed to be executed no matter what *:
char func(int n) {
if (n == 0) return '1';
if (n == 1) return '2';
return '3';
}
* Because not returning a value from a function that should return a value is undefined behaviour.
Now that we have that out of the way, let's have a look at your main():
int main() {
int i;
char str[] = "";
size_t p = strlen(str);
for (i =0 ; i < 5; i++){
str[p++] = func(i);
str[p] = '\0';
p++;
}
printf("%s",str);
return 0;
}
str[] is not big enough to store all the characters you write to it, resulting in undefined behaviour.
Your loop body is written in a weird way, why are you incrementing p twice?
Here a very simple program that writes 5 characters into str:
#include <stdio.h>
char func(int n) {
if (n == 0) return '1';
if (n == 1) return '2';
return '3';
}
int main() {
int i;
// Allocate 6 bytes (5 characters) on the stack
char str[6] = "";
for (i = 0 ; i < 5; i++) {
str[i] = func(i);
}
// Strings *must* be NULL terminated in C
str[5] = 0;
printf("%s",str);
return 0;
}
The size of your str here is "0" (0 using the strlen and 1 using the sizeof operator because it counts the '\0' caracter) so you can not add more element to the str, and if you try, the program will crash. So you have two possibilies here, the first is to declare a fixed table size and the number n will be limited by the size, the second is a dynamic one using mallic. To intialize it to zeros you can just use the memset API.
Well short answer is everything you did would be right if you have in the array enough memory to hold those 5 characters and the \0 if you want to treat it as a string (NUL terminated char array).
"" is a string literal containing only the \0. Length of this string is 0. What about the array? Applying sizeof over it reveals that it is capable of holding one character. (Well it contained \0).
Now with your code you surely did access positions that are beyond the size of the array. This is undefined behavior - mentioned by the C standard.
Solution is to either have an array having size capable of holding the maximum character you would like to store someday. Or you can have a char* to which you can assign address of allocated chunk by using functions like malloc,realloc etc. Benefit of this, you can increase memory as much as you need on runtime depending on the number of characters you want to store.

C - Passing an int value from a char string

I have the following function, and I want to test if the two strings are anagrams. One way I thought about doing it would be to sum the values of each of the characters in the strings and then compare their values.
However, I am getting a segmentation fault in both the for loops when I try to run my program. I am not understanding this correctly, is there anything I am doing incorrectly in my code?
int anagram(char *a, char *b)
{
int sum1 = 0;
int sum2 = 0;
char *p, *q;
for (p=a; p != '\0'; p++) {
sum1 += *p - 'a';
}
for (q=b; q != '\0'; q++) {
sum2 += *q - 'a';
}
if ( sum1 == sum2 )
return 1;
else
return 0;
}
In your for loops you must check
*p != '\0'
*q != '\0'
This is the cause of the seg-fault.
Furthermore, even fixed, that code will give you false positives:
"bc" anagram of "ad"
I suggest you a different approach:
make two arrays of ints sized 256, zero initialized.
Let every item of each array keep the count of every letter (char) of each string.
Finally compare if the two arrays are the same.
I leave the task of writig the code to you.
"p !=0" should be "*p != 0", as it is now you are waiting for the pointer to become null.
Since we're already giving answers about better approaches, here's mine:
Get a list of (preferably small) prime numbers. You need one for every possible character of your input strings, thus when you want to check strings containing only digits 0 to 9 you need 10 prime numbers. Let's take these:
static unsigned const primes[10] = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
Now, since each number has exactly one prime factorisation, and because of multiplication being commutative, you can just build the product of the prime numbers for each character of your string. If they're identical, then for each character holds that it has been the same number of times in both strings. Thus, both strings are anagrams of each other.
unsigned long prime_product(char const * str) {
assert(str != NULL);
unsigned long product = 1;
for (; *str != '\0'; ++str) {
assert(*str >= '0');
assert(*str <= '9');
product *= primes[*str - '0'];
}
return product;
}
char is_anagram(char const * one, char const * two) {
return prime_product(one) == prime_product(two);
}
This should even work to some extend when the product overflows, though then false positives are possible (though their likelihood can be greatly reduced when also comparing the length of the two strings).
As can be seen this version has O(n) time and constant space complexity.
Here is a complete solution for your problem:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int cmp(const void *str1, const void *str2) {
return (*((char*)str1) - *((char*)str2));
}
bool areAnagram(char *str1, char *str2) {
int n1 = strlen(str1);
int n2 = strlen(str2);
if (n1 != n2)
return false;
qsort(str1, n1, 1, &cmp);
qsort(str2, n2, 1, &cmp);
for (int i = 0; i < n1; i++)
if (str1[i] != str2[i])
return false;
return true;
}
int main()
{
char str1[] = "test";
char str2[] = "tset";
if (areAnagram(str1, str2))
printf("The two strings are anagram of each other");
else
printf("The two strings are not anagram of each other");
return 0;
}

Segmentation fault on strlen(char*) but char* IS terminated

I've got a very very simple function which simply converts a char to a char* which represents the binary value of the char with 0's and 1's as chars.
char* stringToBin(char symbol) {
int pos = 0;
int value = (int) symbol;
int rest;
char* result = (char*) malloc(sizeof(char) * 9);
while(value > 0) {
if(value % 2 == 0) {
result[7-pos] = '0';
}
else {
result[7-pos] = '1';
}
pos++;
value = value / 2;
}
while(pos < 8) {
result[7-pos] = '0';
pos++;
}
result[8] = '\0';
puts(result);
puts(strlen(result));
return result;
}
My problem is I can't print the length of the char*. Printing the whole char* works perfect but not calculating the size. I alway get a segmentation fault. I think the problem is pretty simple but I did not get it right now. So please give me the missing hint ;)
The problem is not with the NUL-termination of your string, that's fine. Instead,
puts(strlen(result));
is wrong. puts() expects a C string, and you're giving it a size_t. Write instead:
printf("%zu\n", strlen(result));
(This assumes that the C99 format specifier %zu for size_t is available. If it isn't, then use:
printf("%u\n", (unsigned)strlen(result));
instead.)

Resources