It is sufficient to say that I am new to C so please have show some mercy ;).
I'm trying to compare two strings. The output shouldn't contain common characters. Sadly it does.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char msg[15] = "blueberry";
int c;
int s[15];
int j = 0;
int i = 0;
int k= 0;
int ok = 0;
int t = 0;
while (i < 15 && (c = getchar()) != '\n')
{
s[i] = c;
++i;
}
for (t=j=0; t < 15; ++t)
{
ok = 1;
//printf ("%c", s[t]);
}
for (k=0; msg[k] != '\0'; ++k)
{
if (s[t] == msg[k])
{
ok = 0;
}
}
if (ok == 1)
{
s[j] = s[t];
j++;
}
s[j] = '\0';
for (j = 0; j < 15; ++j)
printf ("%c ", s[j]);
}
The input from the keyboard is blackberry, expected output should've been U but sadly it is not. Any help please. Also why is it entering the nested for loop irrespective of condition?
My big thanks to everyone, it helped me a lot. I've figured out a way & am ok with the output. I've borrowed some ideas from A4L :).
To compare two string, you can use strcmp().
The following is a string compare program that you can use for your reference. I has both array and pointer version for better understanding.
#include <stdio.h>
int strcmp1(char a[], char b[])
{
int i=0;
while (a[i] == b[i]) {
if (a[i] == '\0')
return 0;
i++;
}
return a[i]-b[i];
}
int strcmp2(char *a, char *b)
{
while (*a == *b) {
if (*a == '\0')
return 0;
a++; b++;
}
return *a-*b;
}
int main()
{
char s1[] = "test string1";
char s2[] = "test string";
char s3[] = "aaa";
char s4[] = "bbb";
printf("strcmp1(%s, %s) = %d \n", s1, s2, strcmp1(s1, s2));
printf("strcmp2(%s, %s) = %d \n", s3, s4, strcmp2(s3, s4));
return 0;
}
given that msg contains "blueberry" and s contains "blackberry" this should do it
for (int i=0; i < strlen(msg); i++) {
for (int j = 0; j < strlen(s); j++) {
if (msg[i] != s[j]) {
printf ("%c", msg[i]);
}
}
}
yes it's ugly (using the strlen in the for gives me the chills, but I'm still low on coffeine today ^^)
i guess you want to find the first letter where the input differs from message
here is your own code with some fixes
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char msg[15] = "blueberry";
int c;
char s[15];
int i = 0;
int k= 0;
int ok = 0;
while (i < 15 && (c = getchar()) != '\n')
{
s[i] = (char) c;
++i;
}
// make sure to terminate the string after hitting enter
s[i] = '\0';
printf("input: %s\n", s);
printf("messg: %s\n", msg);
// run through both input and message with one counter
for (k=0; ok == 0 && msg[k] != '\0' && s[k] != '\0'; )
{
// if different chars stop
if (s[k] != msg[k]){
ok = 1;
} else {
// next char
k++;
}
}
if (ok == 1)
{
printf ("diff # index %d -> %c\n", k, msg[k]);
}
else
{
printf ("no diff\n");
}
return 0;
}
#include <stdio.h>
#include <string.h>
//Length to match
int comm(char* s1, char* s2){
int len = 0;
while(*s1 && *s2 && *s1++ == *s2++)
++len;
return len;
}
//commdiffcomm
/*
int commr(char* s1, char* s2){
int len = 0, limit;
int len1,len2;
len1 = strlen(s1);
len2 = strlen(s2);
limit = len1 > len2 ? len2 : len1;
s1 = s1 + len1;
s2 = s2 + len2;
while(limit-- && *--s1 == *--s2)
++len;
return len;
}
//bad
int diff(char* s1, char* s2, int* len1, int* len2){
int len, lenr, s1_len, s2_len, wk_max, i, j;
len = comm(s1, s2);
if(strcmp(s1, s2)==0){
*len1 = *len2 = 0;
return len;
}
lenr = commr(s1, s2);
*len1 = strlen(s1) - len - lenr;
*len2 = strlen(s2) - len - lenr;
return len;
}
*/
int diff(char* s1, char* s2, int* len1, int* len2){
int len, s1_len, s2_len, wk_max, i, j;
len = comm(s1, s2);
if(strcmp(s1, s2)==0){
*len1 = *len2 = 0;
return len;
}
s1_len = strlen(s1 + len + 1);
s2_len = strlen(s2 + len);
wk_max = 0;
for(i = 1; i < s1_len ; i++){
for(j = 0; j < s2_len; j++){
int com_len;
com_len = comm(s1 + len + i, s2 + len + j);
if(wk_max < com_len){
wk_max = com_len;
*len1 = i;
*len2 = j;
}
}
}
return len;
}
int main(){
char str1[16] = "blueberry";
char str2[16] = "blackberry";
char dif1[16] = "";
char dif2[16] = "";
int len0;//length of top to diff pos
int len1;
int len2;
len0 = diff(str1, str2, &len1, &len2);
strncpy(dif1, str1 + len0, len1);
strncpy(dif2, str2 + len0, len2);
if(len1 !=0 && len2 != 0){
printf("%s different %s at position %d length %d (\"%s\")\n", str1, str2, len0, len1, dif1);
printf("%s different %s at position %d length %d (\"%s\")\n", str2, str1, len0, len2, dif2);
} else {
printf("two string is same.");
}
return 0;
}
/*
blueberry different blackberry at position 2 length 2 ("ue")
blackberry different blueberry at position 2 length 3 ("ack")
*/
There are a few problems with the code as is:
You don't null-terminate your input string. Attempting to use it with c string functons would spell trouble. To fix that, change
while (i < 15 && (c = getchar()) != '\n')
{
s[i] = c;
++i;
}
to
while (i < 14 && (c = getchar()) != '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
Your specification is unclear as to whether you want your program to print the letters unique to msg, or to both s and msg. (i.e, do you want msg-s or (msg ∪ s)-(msg ∩ s) Assuming the first, the important part of your program goes like this:
k=0;
for(i=0;i<strlen(msg);i++){
int exists = 0;
for(j=0;!exists && j<strlen(s);j++){
if(msg[j] == s[i])
exists = 1;
}
if(!exists)
msg[k++] = msg[i];
}
s[k] = '\0';
The inner loop checks if s contains the current character in msg. If it does, we don't do anything, but if it doesn't, we append it to the end of a sublist we're creating on top of the bits of msg we've already processed.
your code is a mess even after the rewrite - there are too many errors to describe in detail
/*
blackbery
b l u e b e r r y
. . a c k b e . .
result = non-equal
*/
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char msg[15] = "blueberry";
int c, s[15], i,j,k, ok;
for (i=0; i < 15; i++) s[i] = 0;
for (i=0; i < 15 && (c = getchar()) != '\n'; i++) s[i] = c;
for (ok=1, k=0; msg[k] != '\0'; ++k)
if (s[k] != msg[k]) ok = 0; else s[k] = '.';
for (j = 0; j < 15; ++j) printf ("%c ", msg[j]);
printf("\n");
for (j = 0; j < 15; ++j) printf ("%c ", s[j]);
printf("\nresult = %s\n", ok ? "equal" : "non-equal");
}
Related
I need to make a program that will print characters in a word on how frequent it is used. The unique characters will be printed in increasing order (spaces are ignored), if there are ties the character with lower ascii value will be printed first.
For an example if the input is hello world, the letters "h", "e", "w", "r" and "d" are only used once, the character "o" is used twice and the character "l" is used thrice. Since h,e,w,r,d are tie we should sort it into d,e,h,r,w. Then next would be o since it is used twice and then last is l. Thus if the input is hello world the output must be dehrwol. On my current program the problem is that when there are ties, it would not sort it alphabetically so the output is hewrdol instead of dehrwol.
This is the code I have written
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int times[256];
int cmpLetters(const void* a, const void* b)
{
return (times[*(char*)a] > times[*(char*)b]) - (times[*(char*)a] < times[*(char*)b]);
}
int main()
{
char letters[256];
int i, j, k, lnum, t;
char s[1000];
fgets(s, sizeof(s), stdin);
// Init occurrences as 0
memset(times, 0, sizeof(times));
for (i = lnum = 0; s[i] != '\0'; i++)
if (times[s[i]]++ == 0)
letters[lnum++] = s[i];
// Sort letters by number of occurrences
qsort(letters, lnum, sizeof(char), cmpLetters);
char* new = malloc(sizeof(char) * (i + 1));
for (j = k = 0; j < lnum; j++)
for (i = 0; i < times[letters[j]]; i++)
new[k++] = letters[j];
// new[k] = '\0';
for (i = 0; i<lnum; i++)
{
if(letters[i] != '\n' && letters[i] !=' ')
printf("%c",letters[i]);
}
printf("\n\n");
return 0;
}
In this for loop
for (i = lnum = 0; s[i] != '\0'; i++)
if (times[s[i]]++ == 0)
letters[lnum++] = s[i];
you are not checking whether s[i] represents a letter.
The comparison function
int cmpLetters(const void* a, const void* b)
{
return (times[*(char*)a] > times[*(char*)b]) - (times[*(char*)a] < times[*(char*)b]);
}
compares only characters without comparing also their frequencies.
This code snippet
char* new = malloc(sizeof(char) * (i + 1));
for (j = k = 0; j < lnum; j++)
for (i = 0; i < times[letters[j]]; i++)
new[k++] = letters[j];
does not make sense because the array new is not used further in the program. It only produces a memory leak.
The program will be simpler if to introduce a structure that contains two data members that store a letter and its frequency.
Here is a demonstration program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
struct Pair
{
char c;
size_t n;
};
int cmp( const void *a, const void *b )
{
const struct Pair *p1 = a;
const struct Pair *p2 = b;
int result = ( p2->n < p1->n ) - ( p1->n < p2->n );
if (result == 0)
{
result = ( p2->c < p1->c ) - ( p1->c < p2->c );
}
return result;
}
int main( void )
{
enum { N = 1000} ;
char s[N];
fgets( s, sizeof( s ), stdin );
size_t n = 0;
for (size_t i = 0; s[i] != '\0'; ++i)
{
if (isalpha( ( unsigned char )s[i] ))
{
size_t j = 0;
while (j != i && s[j] != s[i]) ++j;
n += j == i;
}
}
if (n != 0)
{
struct Pair pairs[n];
memset( pairs, 0, n * sizeof( struct Pair ) );
for (size_t i = 0, m = 0; s[i] != '\0'; i++)
{
if (isalpha( ( unsigned char )s[i] ))
{
size_t j = 0;
while (j != m && pairs[j].c != s[i]) ++j;
if (j == m)
{
pairs[m].c = s[i];
++pairs[m].n;
++m;
}
else
{
++pairs[j].n;
}
}
}
qsort( pairs, n, sizeof( *pairs ), cmp );
for (size_t i = 0; i < n; i++)
{
putchar( pairs[i].c );
}
putchar( '\n' );
}
}
The program output might look like
hello world
dehrwol
I was trying this pattern matching method in C but whenever I give all the input, the vscode terminal waits for a while and just stops the program without any warnings/message. Can anyone point to what is wrong here?
#include <stdio.h>
#include <string.h>
int main()
{
char STR[100], PAT[100], REP[100], ANS[100];
int i, m, j, k, flag, slP, slR, len;
i = m = k = j = flag = len = 0;
printf("\nMain String: ");
gets(STR);
printf("\nPattern String: ");
gets(PAT);
slP = strlen(PAT);
printf("\nReplace String: ");
gets(REP);
slR = strlen(REP);
while (STR[i] != '\0')
{
if (STR[i] = PAT[j])
{
len = 0;
for (k = 0; k < slP; k++)
{
if (STR[k] = PAT[k])
len++;
}
if (len == slP)
{
flag = 1;
for (k = 0; k < slR; k++, m++)
ANS[m] = REP[k];
}
}
else
{
ANS[m] = STR[i];
m++;
i++;
}
}
if (flag == 0)
{
printf("\nPattern not found!");
}
else
{
ANS[m] = '\0';
printf("\nResultant String: %s\n", ANS);
}
return 0;
}
There are multiple problems in the code:
using gets() is risky, this function was removed from the C Standard because it cannot be used safely.
if (STR[i] = PAT[j]) copied the pattern to the string. You should use:
if (STR[i] == PAT[j])
similarly, if (STR[k] = PAT[k]) is incorrect. You should compare PAT[k] and STR[i + k]:
if (STR[i + k] == PAT[k])
you should test for buffer overflow for the output string as replacing a short string by a larger one may produce a string that will not fit in ANS
you do not increment i properly.
Here is a modified version:
#include <stdio.h>
int getstr(const char *prompt, char *dest, int size) {
int c, len = 0;
printf("%s", prompt);
while ((c = getchar()) != EOF && c != '\n') {
if (len + 1 < size)
dest[len++] = c;
}
if (size > 0)
dest[len] = '\0';
printf("\n");
if (c == EOF && len == 0)
return -1;
else
return len;
}
int main() {
char STR[100], PAT[100], REP[100], ANS[100];
int i, m, k, flag;
if (getstr("Main String: ", STR, sizeof STR) < 0)
return 1;
if (getstr("Pattern String: ", PAT, sizeof PAT) < 0)
return 1;
if (getstr("Replace String: ", REP, sizeof REP) < 0)
return 1;
i = m = flag = 0;
while (STR[i] != '\0') {
if (STR[i] == PAT[0]) { // initial match
// compare the rest of the pattern
for (k = 1; PAT[k] != '\0' && PAT[k] == STR[i + k]; k++)
continue;
if (PAT[k] == '\0') { // complete match
flag = 1;
// copy the replacement string
for (k = 0; REP[k] != '\0'; k++) {
if (m + 1 < sizeof ANS)
ANS[m++] = REP[k];
}
i += k; // skip the matching characters
continue;
}
}
// otherwise copy a single character
if (m + 1 < sizeof ANS)
ANS[m++] = STR[i];
i++;
}
ANS[m] = '\0';
if (flag == 0) {
printf("Pattern not found!\n");
} else {
printf("Resultant String: %s\n", ANS);
}
return 0;
}
I want to insert string to the array until I type "ok". Why I am getting just "ok" and original array at the output?
int main(void)
{
char b[20];
char* str[10] = { "1","2" };
int i = 2;
while (1) {
gets(b);
if (strcmp(b, "ok") == 0) break;
str[i] = b;
i++;
}
for (int j = 0; j < i; j++)
printf("%s ", str[j]);
return 0;
}
You need to allocate a string on each iteration:
int main(void)
{
char* b;
char* str[10] = { "1","2" };
int i = 2;
while (1) {
b = malloc(20);
gets(b);
if (strcmp(b, "ok") == 0) break;
str[i] = b;
i++;
}
for (int j = 0; j < i; j++)
printf("%s ", str[j]);
// free allocated strings
while (i > 2)
free(str[--i]);
return 0;
}
They all point to b, which gets overwritten in each iteration.
You need to create a copy of the string when you assign it:
str[i] = strdup(b);
You also may consider using fgets instead of gets; however, you will need to remove the newline:
size_t size;
fgets(str, 20, stdin);
size = strlen(str);
if(str[size-1] == '\n')
str[size-1] = '\0';
Also, print a newline at the end of your program, so it won't interfere with the shell:
putchar('\n');
Full code:
int main(void)
{
char b[20];
char* str[10] = { "1","2" };
int i = 2;
while (1) {
size_t size;
fgets(str, 20, stdin);
size = strlen(str);
if(str[size-1] == '\n')
str[size-1] = '\0';
if (strcmp(b, "ok") == 0)
break;
str[i] = strdup(b);
i++;
}
for (int j = 0; j < i; j++)
printf("%s ", str[j]);
putchar('\n');
return 0;
}
You need to make a copy of the input string, then save a pointer to the copy of the input string in your array. Something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char b[20];
char *str[10] = { "1","2" };
int i = 2;
char *p;
size_t lenb;
for(i = 2 ; i < 10 ; ++i)
{
fgets(b, sizeof(b), stdin);
lenb = strlen(b);
if(lenb > 0 && *(b+lenb-1) == '\n')
{
*(b+lenb-1) = '\0'; /* overwrite the trailing \n */
lenb = strlen(b);
}
if (strcmp(b, "ok") == 0)
break;
p = malloc(lenb+1);
strcpy(p, b);
str[i] = p;
}
for (int j = 0; j < i; j++)
printf("%s\n", str[j]);
return 0;
}
I got some troubles while I'm trying to set a char into a char* ("string")
I got lines, which is all the txt lines I fetched before, and now I'm trying to assign a char to my char*, to filter it.
Here is my actual code :
void TreatDatas(char** lignes, int sizeLignes){ // all the lines, and the size of it.
char** finalArray;
finalArray = malloc(2048 * sizeof(char*));
int sizeOfFinalArray = 0;
int i;
int j;
char* s;
char* savedCurrentString = "";
int sizeOfCurrentString = 0;
for (i = 0; i< sizeLignes; i++){
s = lignes[i];
for (j = 0; j < strlen(s); j++){ // I don't pass the first condition the first loop
if (s[j] == ',' || s[j] == '.' || s[j] == ' ' || s[j] == '\n' || s[j] == ';' || s[j] == ':'){ // Separators list
finalArray[sizeOfFinalArray] = malloc(strlen(savedCurrentString) + 1);
strcpy(finalArray[sizeOfFinalArray], savedCurrentString);
savedCurrentString = "";
sizeOfCurrentString = 0;
}else{
printf("%c , %s \n", s[j], savedCurrentString); // L - ""
printf("%d", sizeOfCurrentString); // 0
strncpy(savedCurrentString, s[j], 1); // error here
}
}
}
free(finalArray);
}
Ok I change a bit the code, now it's better, but seems to duplicate some elements. And I don't know why. Excuse me, I'm a C beginer, but I'm curious and trying to understand how that works.
void TreatDatas(char** lignes, int sizeLignes){
char** finalArray;
finalArray = malloc(2048 * sizeof(char*));
int sizeOfFinalArray = 0;
int i;
int j;
char* s;
char* savedCurrentString = "";
int sizeOfCurrentString = 0;
for (i = 0; i< sizeLignes; i++){
s = lignes[i];
printf("line : %d \n %s \n", i, s);
StringSpliter(s);
// for (j = 0; j < strlen(s); j++){
// finalArray[sizeOfFinalArray] = malloc(strlen(savedCurrentString) + 1);
// }
}
free(finalArray);
}
char * StringSpliter(char* input){
char separators[5][2] = {" ", ",", ";", ":", "."};
char ** buffer;
int bufferSize = 0;
int i;
for (i = 0; i < 5; i++){
char* token = strtok(input, separators[i]);
printf("%s", token);
while( token != NULL )
{
printf( " %s\n", token );
token = strtok(NULL, separators[i]);
}
}
printf("\n");
return "OSEF";
}
My output
I have this code, what i want it to do is print the string that represents the word, and print the number of times it occurred in the file, instead it outprints something liek this: (a load of blank space) and then this number -1076720020, which i have no idea where it came from, how would i go about fixing this?
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
struct podatki {
char beseda[1000];
int frekvenca;
};
void zamenjaj(char *str1, char *str2) {
char *beseda2 = (char *)malloc((strlen(str1) + 1) * sizeof(char));
strcpy(beseda2, str1);
strcpy(str1, str2);
strcpy(str2, beseda2);
free(beseda2);
}
int posodobi(struct podatki s[], const char unit[], int count) {
int i =0;
for (i = 0; i < count; i++) {
if (strcmp(s[i].beseda, unit) == 0) {
s[i].frekvenca++;
return count;
}
}
strcpy(s[count].beseda, unit);
s[count].frekvenca++;
return (count + 1);
}
int main() {
int stBes;
scanf("%d", &stBes);
//zacetne deklaracije
struct podatki s[1000];
char string[1000], unit[2000], c;
int i = 0;
int frekvenca = 0;
int j = 0;
int count = 0;
int num = 0;
//branje
for (i = 0; i < 1000; i++) {
s[i].frekvenca = 0;
}
i = 0;
do {
fflush(stdin);
c = getchar();
string[i++] = c;
} while (c != '\n');
//pretvori v majhne crke
char *p;
for (p = string; *p != '\0'; ++p) {
*p = tolower(*p);
}
string[i - 1] = '\0';
for (i = 0; i < strlen(string); i++) {
while (i < strlen(string) && string[i] != ' ' && !ispunct(string[i])) {
unit[j++] = string[i++];
}
if (j != 0) {
unit[j] = '\0';
count = posodobi(s, unit, count);
j = 0;
}
}
int a;
for (i = 0; i < count; ++i) {
for (j = i + 1; j < count; ++j) {
if (s[i].frekvenca < s[j].frekvenca) {
a = s[i].frekvenca;
s[i].frekvenca = s[j].frekvenca;
s[j].frekvenca = a;
zamenjaj(s[i].beseda, s[j].beseda);
}
}
}
for (i = 0; i < count; i++) {
for (j = 1; j < count; j++) {
if (s[i].frekvenca == s[j].frekvenca){
if (strcmp(s[i].beseda, s[j].beseda) < 0) {
a = s[i].frekvenca;
s[i].frekvenca = s[j].frekvenca;
s[j].frekvenca = a;
zamenjaj(s[i].beseda, s[j].beseda);
}
}
}
}
//printanje
for (i = 0; i < stBes; i++) {
printf("%s\t %d\n", s[i].beseda, s[i].beseda);
if (s[i].frekvenca > 1) {
num++;
}
}
return 0;
}
The problem is that you convert the string to lower case before nul terminating it.
Here
i = 0;
do {
fflush(stdin);
c = getchar();
string[i++] = c;
} while (c != '\n');
/* Goes here <---------------------+ */
/* | */
//pretvori v majhne crke | */
char *p; /* | */
for (p = string; *p != '\0'; ++p) {/* | */
*p = tolower(*p);/* | */
} /* | */
/* | */
string[i - 1] = '\0'; /* ---------------------+ */
You should also remove the fflush(stdin) and instead use getchar() to fetch the white space characters ignored by the previous scanf(), and please use scanf() correctly and check it's returned value.