how to compare two 2 d string without using strcmp - c

I have data file in which some data is kept.
example: welcome user HII if while
I have made 2D character array to store all the keywords in c.
now I want two know if the data file contain the keyword or not.
enter code here
for(i=0;i<32;i++)
for(j=0;j<no_of_words_in_file;j++)
if(k[i]==t[j])
printf("%s is keyword",t[j]);
here the k[i] represents the 2D character array where all the keywords in c are stored and t[i] represents the 2D character array where all the words of file are stored.
I want to compare these 2D arrays without using strcmp.

To compare two strings without using standard C functions you can use a loop like that
#include <stdio.h>
int main(void)
{
char key[] = "while";
char word1[] = "while";
char word2[] = "when";
size_t i = 0;
while ( key[i] != '\0' && key[i] == word1[i] ) ++i;
int equal = key[i] == word1[i];
printf( "key == word1: = %d\n", equal );
i = 0;
while ( key[i] != '\0' && key[i] == word2[i] ) ++i;
equal = key[i] == word2[i];
printf( "key == word2: = %d\n", equal );
return 0;
}
The program output is
key == word1: = 1
key == word2: = 0
Or you can write a separate function. For example
#include <stdio.h>
int equal( const char *s1, const char *s2 )
{
while ( *s1 != '\0' && *s1 == *s2 )
{
++s1; ++s2;
}
return *s1 == *s2;
}
int main(void)
{
enum { N = 10 };
char key[][N] ={ "if", "while" };
const size_t N1 = sizeof( key ) / sizeof( *key );
char words[][N] = { "welcome", "user", "HII", "if", "while" };
const size_t N2 = sizeof( words ) / sizeof( *words );
for ( size_t i = 0; i < N2; i++ )
{
for ( size_t j = 0; j < N1; j++ )
{
if ( equal( key[j], words[i] ) )
{
printf( "\"%s\" == \"%s\"[%zu]\n", key[j], words[i], i );
}
}
}
return 0;
}
the program output is
"if" == "if"[3]
"while" == "while"[4]

Related

applying cipher code given as argv to userinput

I am trying to write a function that takes in variables cipher, userinput, alphabet and outputs the replace letters. for example at execution it takes in an argument argv ZYXWVUTSRQPONMLKJIHGFEDCBA. requests a user to input anything then switches only the letters for example input aBc should output zYx
// function that takes in cipher(c), userinput(u) and alphabet(a) and outputs cipher text
void cipher_text(string c, string u, string a)
{
string result = u;
for (int i = 0; i < strlen(u); i++)
{
for (int k = 0; k < strlen(a); k++)
{
if (tolower(u[i]) == a[k])
{
if(islower(u[i]))
{
result[i] = tolower(c[k]);
printf("%s %s\n",result,c);
}
else
{
result[i] = toupper(c[k]);
}
}
}
}
// printf("ciphertext: %s\n", result);
}
with cipher as YUKFRNLBAVMWZTEOGXHCIPJSQD
and userinput as abcd
I was expecting yukf but got qidc
The problem of the function is this inner for loop
for (int k = 0; k < strlen(a); k++)
{
if (tolower(u[i]) == a[k])
{
if(islower(u[i]))
{
result[i] = tolower(c[k]);
printf("%s %s\n",result,c);
}
else
{
result[i] = toupper(c[k]);
}
}
}
You need to break it as soon as a letter is found in the string pointed to by the pointer a. Otherwise there can be a chain of changes.
Also using the function strlen is inefficient and redundant.
Instead of the for loop you could use standard function strchr.
The function can be declared and defined the following way
string cipher_text( string c, string u, string a )
{
for ( string p = u; *p != '\0'; p++ )
{
string pos = strchr( a, tolower( ( unsigned char )*p ) );
if ( pos != NULL )
{
size_t i = pos - a;
*p = islower( ( unsigned char )*p )
? tolower( c[i] )
: c[i];
}
}
return u;
}
Pay attention to that instead of the typedef name string it is better to use its underlaying type char *.
In this case the function can look the following way as shown in the demonstration program below.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char * cipher_text( const char *c, char *u, const char *a )
{
for (char *p = u; *p != '\0'; p++)
{
const char *pos = strchr( a, tolower( ( unsigned char )*p ) );
if (pos != NULL)
{
size_t i = pos - a;
*p = islower( ( unsigned char )*p )
? tolower( c[i] )
: c[i];
}
}
return u;
}
int main( void )
{
const char *c = "XYZ";
const char *a = "abc";
char u[] = "c_B_a";
puts( cipher_text( c, u, a ) );
}
The program output is
z_Y_x

How to return a new string in a function in c?

Hello my function should print str1 beginning with str2 (if found), I would like to return a new string (newStr) in the following function but it doesn't work. Some help please
char *myFunction(char *str1, char *str2){
int strLen;
int i;
int j;
char temp;
char *newStr;
strLen=0;
while(str1[strLen]!='\0'){
strLen++;
}
i=0;
j=0;
while(i<=strLen && str1[i]!='\0'){
if(str1[i]==str2[j] ){
newStr[i]=str1[i];
j++;
} else {
newStr[i]=str1[i];
}
i++;
}
return (newStr);
}
char *newStr is uninitialized; you must allocate memory to it, before assigning any value to it.
Allocate memory using malloc or calloc.
For starters the function should be declared like
char * myFunction( const char *str1, const char *str2 );
because the passed strings are not being changed within the function.
If the function has to return a new string then you need to allocate a character array where the string will be stored. However you are using an uninitialized pointer newStr
char *newStr;
The condition in the while loop
while(i<=strLen && str1[i]!='\0'){
does not make a great sense.
The variable j in fact is not used.
The if-else statement within the while loop does not make a sense.
If you are allowed to use standard C string functions then your function can be implemented very easy.
#include <string.h>
char * myFunction( const char *s1, const char *s2 )
{
char *p = strstr( s1, s2 );
if ( p != NULL )
{
size_t n = strlen( p );
s1 = p;
p = malloc( n + 1 );
if ( p != NULL ) memcpy( p, s1, n + 1 );
}
return p;
}
Otherwise the function can be defined the following way
char * myFunction( const char *s1, const char *s2 )
{
size_t n1 = 0;
while ( s1[n1] ) ++n1;
size_t n2 = 0;
while ( s2[n2] ) ++n2;
char *p = NULL;
if ( !( n1 < n2 ) )
{
int found = 0;
size_t i = 0;
while ( !found && i < n1 - n2 + 1 )
{
if ( s1[i] == s2[0] )
{
size_t j = 1;
while ( j < n2 && s1[i + j] == s2[j] ) ++j;
found = j == n2;
}
if ( !found ) ++i;
}
if ( found )
{
p = malloc( n1 - i + 1 );
if ( p != NULL )
{
size_t j = 0;
do
{
p[j] = s1[i + j];
} while ( p[j++] != '\0' );
}
}
}
return p;
}

How to write function that return dynamic allocated string?

I have assignment that to use function char *slova(const char *s) which returns dynamically allocated string that is only made of small and big letters. It's forbidden to use string.h library.
char *slova(const char *s)
{
char *new;
int br = 0;
new = (char *)malloc(sizeof(s));
for (int i = 0; i != '\0'; i++)
if(s[i] >= 'A' && s[i] <= 'z')
{
new[br] = s[i];
br++;
}
return new;
}
I know there are some other characters other than small and big letters between A and z in ASCII code, so don't worry about that. For some reason this code doesn't work and I don't know why.
sizeof(s) will return not the buffer size but the size of the pointer s.
i != '\0' is wrong. This means i != 0 and prevent it from entering the loop because initial value of i is 0.
You forgot to terminate the resulting string by adding a terminating null-character.
Casting the result of malloc() in C is discouraged.
Fixed code:
char *slova(const char *s){
char *new;
int br = 0;
// calculate the length
for (int i = 0; s[i] != '\0'; i++)
if(s[i] >= 'A' && s[i] <= 'z'){
br++;
}
// allocate buffer
new = malloc(br + 1);
if (new == NULL) return NULL;
// actually create the string
br = 0;
for (int i = 0; s[i] != '\0'; i++)
if(s[i] >= 'A' && s[i] <= 'z'){
new[br] = s[i];
br++;
}
new[br] = '\0';
return new;
}
Look carefully at your function declaration
char *slova(const char *s){
^^^^^^^^^^^^^
Its parameter has the pointer type const char *. Thus in this statement
new = (char *)malloc(sizeof(s));
the expression sizeof(s) yields the size of a pointer that usually is equal to 8 or 4 bytes depending on the used system. That is this expression does not provide the length of the passed string.
Also the body of this loop
for (int i = 0; i != '\0'; i++)
never gets the control because the condition i != '\0' at once evaluates to false because the variable i was initialized by zero.
The function can look the following way as it is shown in the demonstrative program below. It does not use functions from the header <string.h>.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
char * slova( const char *s )
{
size_t n = 0;
for ( const char *t = s; *t != '\0'; ++t )
{
if ( isalpha( ( unsigned char )*t ) ) ++n;
}
char * result = malloc( ( n + 1 ) *sizeof( char ) );
if ( result != NULL )
{
char *p = result;
for ( ; *s; ++s)
{
if ( isalpha( ( unsigned char )*s ) )
{
*p++ = *s;
}
}
*p = '\0';
}
return result;
}
int main(void)
{
const char *s = "H#e#l#l#o W#o#r#l#d";
char *p = slova( s );
if ( p ) puts( p );
free( p );
return 0;
}
The program output is
HelloWorld
If you are not allowed also to use functions from the header <ctype.h> then the function can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
char * slova( const char *s )
{
const char *upper_case = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char *lower_case = "abcdefghijklmnopqrstuvwxyz";
size_t n = 0;
for ( const char *t = s; *t != '\0'; ++t )
{
const char *letter = lower_case;
if ( *t < lower_case[0] )
{
letter = upper_case;
}
while ( *letter && *letter < *t ) ++letter;
if ( *letter == *t ) ++n;
}
char * result = malloc( ( n + 1 ) *sizeof( char ) );
if ( result != NULL )
{
char *p = result;
for ( ; *s; ++s)
{
const char *letter = lower_case;
if ( *s < lower_case[0] )
{
letter = upper_case;
}
while ( *letter && *letter < *s ) ++letter;
if ( *letter == *s )
{
*p++ = *s;
}
}
*p = '\0';
}
return result;
}
int main(void)
{
const char *s = "H#e#l#l#o W#o#r#l#d";
char *p = slova( s );
if ( p ) puts( p );
free( p );
return 0;
}
Again the program output is
HelloWorld

Stuck Finding Bug in LeetCode Question Solution

The problem is simple: take a string, and reverse the position of ONLY letters (lower or uppercase). Leave any special characters where they are. My solution:
char * reverseOnlyLetters(char * S){
int Len = strlen(S);
char *StrBeg, *StrEnd, tempCh;
bool FoundStart = 0, FoundEnd = 0;
StrBeg = S;
StrEnd = S + (Len - 1);
for (int i = 0; i < (Len/2); i++)
{
if (((*StrBeg>= 'A') && (*StrBeg <= 'Z')) || ((*StrBeg >= 'a') && (*StrBeg <= 'z')))
{
FoundStart = 1;
}
else
{
StrBeg++;
}
if (((*StrEnd >= 'A') && (*StrEnd <= 'Z')) || ((*StrEnd >= 'a') && (*StrEnd <= 'z')))
{
FoundEnd = 1;
}
else
{
StrEnd--;
}
if(FoundStart && FoundEnd)
{
tempCh = *StrEnd;
*StrEnd = *StrBeg;
*StrBeg = tempCh;
StrBeg++;
StrEnd--;
FoundStart = 0;
FoundEnd = 0;
}
}
return S;
}
The issue is a testcase like "a-bC-dEf-ghIj" fails; the "E" and the "f" in the middle either don't get swapped at all, or (as I suspect), get swapped, but then get swapped BACK. Anyone see what I'm doing wrong?
Problem is this for (int i = 0; i < (Len/2); i++).
If lenght of string is even, it's ok, but in case it's even it doesn't go through the middle character. E in this "a-bC-dEf-ghIj" case, so it can't switch it with f.
The approach using this for loop
for (int i = 0; i < (Len/2); i++)
is incorrect. Let's assume that the string is "#AB". The result string will look like "#BA"
But using your loop you will have (as Len / 2 is equal to 1)
for (int i = 0; i < 1; i++)
In the first and single iteration of the loop the pointer StrBeg will be incremented
StrBeg++;
because the pointed character is not a letter.
So nothing will be reversed.
The function can be written simpler the following way
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char * reverse_letters( char *s )
{
for ( char *first = s, *last = s + strlen( s ); first < last; ++first )
{
while ( first != last && !isalpha( ( unsigned char )*first ) ) ++first;
while ( last != first && !isalpha( ( unsigned char )*--last ) );
if ( first != last )
{
char c = *first;
*first = *last;
*last = c;
}
}
return s;
}
int main( void )
{
char s[] = "one, two, three";
puts( s );
puts( reverse_letters( s ) );
char s1[] = "#AB";
puts( s1 );
puts( reverse_letters( s1 ) );
}
The program output is
one, two, three
eer, hto, wteno
#AB
#BA

Copying strings between vectors of strings in C

I have an array of char pointers (string array), which contains some duplicate values. I've found an algorithm that truncates the array by removing its duplicate values.
Here is a code sample :
int i, j , k;
int n = 10;
char *teams[n];
for(i=0;i<n;i++){
for(j=i+1;j<n;){
if(*(team[j]==*(team[i])){
for(k=j;k<n;k++){
//strcpy(team[k], team[k+1]);
team[k] = team[k+1];
}
n--;
}else{
j++;
}
}
}
I've read that the only way to copy strings between string arrays is to use strcpy(s1, s2). But in my case I can't use it, because strcpy function permits to copy s2 into s1 only if s2 has a lenght equal or bigger than the lenght of s1. So how can I implement this algorithm if I can't put the string pointed by the pointer team[k+1] in team[k] ?
It seems you need to remove duplicated string representations instead of duplicated addresses to strings.
If so then this if statement (if to add missed closed parenthesis)
if( *(team[j] ) ==*( team[i] ) ){
compares only first characters of strings instead of comparing strings pointed to by the pointers.
In this loop
for(k=j;k<n;k++){
//strcpy(team[k], team[k+1]);
team[k] = team[k+1];
}
each time when a duplicates string is found there is copied the whole array of pointers. Moreover there is an attempt to access memory beyond the array in this statement when k is equal to n-1
team[k] = team[k+1];
^^^^
You can write a separate function that will "remove" duplicates. The function can for example return pointer after the last unique element in the modified array.
#include <stdio.h>
#include <string.h>
char ** unique( char *s[], size_t n )
{
size_t i = 0;
for ( size_t j = 0; j < n; j++ )
{
size_t k = 0;
while ( k < i && strcmp( s[k], s[j] ) != 0 ) ++k;
if ( k == i )
{
if ( i != j ) s[i] = s[j];
++i;
}
}
return s + i;
}
int main(void)
{
char * s[] = { "A", "B", "A", "C", "A" };
const size_t N = sizeof( s ) / sizeof( *s );
for ( size_t i = 0; i < N; i++ ) printf( "%s ", s[i] );
printf( "\n" );
char **p = unique( s, N );
size_t n = p - s;
for ( size_t i = 0; i < n; i++ ) printf( "%s ", s[i] );
printf( "\n" );
return 0;
}
The program output is
A B A C A
A B C
#include <stdio.h>
#include <string.h>
unsigned dedup(char **arr, unsigned count)
{
unsigned this, that ;
for(this=0;this<count;this++){
for(that=this+1;that<count;){
if( strcmp(arr[that], arr[this])) {that++; continue; }
#if PRESERVE_ORDER
memmove(arr+that, arr+that+1, (--count - that) * sizeof arr[that] );
#else
arr[that] = arr[--count];
#endif
}
}
return count; /* the count after deduplication */
}
char *array[] = { "one", "two", "three", "two", "one", "four", "five", "two" };
int main(void)
{
unsigned count, index;
count = dedup(array, 8);
for (index = 0; index < count; index++) {
printf("%s\n", array[index] );
}
return 0;
}
[UPDATED]: I added the PRESERVE_ORDER version

Resources