why is my function encodeChar does not work? - c

The code below is supposed to allow the user to enter two character strings s and t, an array of structures and the size
of array as parameters, encodes the characters in s to t, and passes the encoded string t to the caller via call by reference.
I cannot understand why my function encodeChar is wrong. I have already tried to use the indexing method and it is similar to the correct answer. But when i input
1
3
a
b
b
c
c
d
3
abcd
4
, the output is abdd. I do not understand where is my mistake. Please have me resolve my misconceptions.
#include <string.h>
typedef struct {
char source;
char code;
} Rule;
void createTable(Rule *table, int *size);
void printTable(Rule *table, int size);
void encodeChar(Rule *table, int size, char *s, char *t);
int main()
{
char s[80], t[80], dummychar, *p;
int size, choice;
Rule table[100];
printf("Select one of the following options:\n");
printf("1: createTable()\n");
printf("2: printTable()\n");
printf("3: encodeChar()\n");
printf("4: exit()\n");
do {
printf("Enter your choice: \n");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("createTable(): \n");
createTable(table, &size);
break;
case 2:
printf("printTable(): \n");
printTable(table, size);
break;
case 3:
scanf("%c",&dummychar);
printf("Source string: \n");
fgets(s, 80, stdin);
if (p=strchr(s,'\n')) *p = '\0';
encodeChar(table,size,s,t);
printf("Encoded string: %s\n", t);
break;
default:
break;
}
} while (choice < 4);
return 0;
}
void printTable(Rule *table, int size)
{
int i;
for (i=0; i<size; i++)
{
printf("%d: %c->%c\n", i+1, table->source, table->code);
table++;
}
}
void createTable(Rule *table, int *size)
{
/*edit*/
/* Write your code here */
/*edit*/
/* Write your code here */
int i;
char dummy[80];
printf("Enter number of rules: \n");
scanf("%d", size); // dont careless here
for(i=0; i< *size; i++){
printf("Enter rule %d: \n", i+1);
fgets(dummy, 80,stdin); // why need to use this twice
printf("Enter source character: \n");
scanf("%c", &table[i].source);
fgets(dummy,80,stdin);// why
printf("Enter code character: \n ");
scanf("%c", &table[i].code);
}
/*end_edit*/
/*end_edit*/
}
void encodeChar(Rule *table, int size, char *s, char *t)
{
/*edit*/
/* Write your code here */// this is wrong
int i, j;
for(i = 0 ; s[i] != '\0'; i++){
for(j = 0; j < size; j++){
if(s[i] == table[j].source){
*t = table[j].code;
}
else{
*t = s[i];
}
}
t++;
}
*t = '\0';
/*edit*/
/* this is correct
int i;
while(*s!='\0'){
for(i = 0; i < size; i++){
if(*s != table[i].source)
*t = *s;
else
*t = table[i].code;
t++;
s++;
}
}
*t = '\0';
*/
}

Here a paper sheet and a pencil would be enough.
Just follow your code for abcd. The relevant part is
for(i = 0 ; s[i] != '\0'; i++){
for(j = 0; j < size; j++){
if(s[i] == table[j].source){
*t = table[j].code;
}
else{
*t = s[i];
}
}
t++;
}
*t = '\0';
Let's go:
i is 0, s[i] is a
j is 0, table[j].source is a: *t receives b
j is 1, table[j].source is b: *t recieves (back) a !...
Only the last rule can be applied with your code...
A simple fix would be to break out of the loop when a rule is applied to prevent the following ones to roll back the change:
for(i = 0 ; s[i] != '\0'; i++){
for(j = 0; j < size; j++){
if(s[i] == table[j].source){
*t = table[j].code;
break; // do not examine other rules
}
else{
*t = s[i];
}
}
t++;
}
*t = '\0';
But if the same character is changed by multiple rules, this code would use the first one, while the correct code would use the last one, so this would be more consistent:
for(i = 0 ; s[i] != '\0'; i++){
for(j = size-1; j >= 0; j--){ // examine rules in descending order
...
Anyway, there are still possible improvements here, so you could probably post it to CodeReview for advices for best practices...

Related

rearranging a char array with strncpy in C

I am trying to change the sorting of a the arr list which could consist of zero, one, two as the inputted and stored values for arr. The stringreplace function is meant to shift every single element by one so the new sorting would be one, two, zero. I am trying to replace the elements with one another by using the strncpy function but I think it is a bit faulty, how could i fix this?
strncpy function
char stringreplace( char a[], int b){
for(int j = 0; j > b -1; j++){
strncpy(a[j], a[j+1], sizeof(a));}
for(int j = 0; j > b; j++){
printf("%s",a[j]);}
}
main function
int main()
{
char input[100];
char arr[100]= {0};
int number;
printf("Input the number of strings: ");
scanf("%d", &number);
for(int i= 0; i < number; i++){
printf("Input the number of strings: ");
scanf("%s", input);
arr[i] = input;
}
stringreplace(arr, number);
return 0;
}
You may consider allocating strings dynamically, assigning a pointer for each string into an array words, and then rotating each pointer in the array to the left.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void lrot_words(char *words[], int n);
int main(void)
{
char *p, word[100], *words[100];
int i, num_words;
printf("Enter the number of words: ");
scanf("%d", &num_words);
for(i = 0; i < num_words; i++){
printf("Enter a word: ");
scanf("%s", word);
if ((p = malloc(strlen(word) + 1)) == NULL) {
fprintf(stderr, "Error: malloc failed\n");
exit(EXIT_FAILURE);
}
words[i] = strcpy(p, word);
}
lrot_words(words, num_words);
for (i = 0; i < num_words; i++) {
printf("%s\n", words[i]);
}
return 0;
}
void lrot_words(char *words[], int n)
{
char *temp = words[0];
int i;
for (i = 0; i < n - 1; i++) {
words[i] = words[i+1];
}
words[i] = temp;
}

Trying to remove substring from string in C, keep failing

I know this question has been asked many times before but I simply cannot get my head around what I am doing wrong. Everytime I make some progress I get a new error. The code I am using is really basic because I am a newbie and our professor requires the usage of scanf and gets. This is my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 100
int identify(char[], char[]);
int remove(char[], char[], int);
int scan(choice)
{
while(choice < 0 || choice > 7)
{
printf("Invalid input, choose again\n");
scanf("%d", &choice);
}
return choice;
}
int main()
{
char sentence[MAX_SIZE], word[MAX_SIZE];
int choice, i, j, k, deikths;
printf("Choose one of the following:\n");
printf("1. Give sentence\n");
printf("2. Subtract a word\n");
printf("3. Add a word\n");
printf("4. Count the words\n");
printf("5. Count the sentences\n");
printf("6. Count the characters\n");
printf("7. Is the phrase a palindrome?\n");
printf("0. Exit\n");
scanf("%d", &choice);
if(scan(choice) == 1)
{
printf("Give sentence:\n");
gets(sentence);
gets(sentence);
printf("%s\n", sentence);
}
else(scan(choice) == 2);
{
printf("Give word you want to subtract\n");
gets(word);
printf("%s", word);
deikths = identify(sentence, word);
if(deikths != -1)
{
remove(sentence, word, deikths);
printf("Sentence without word: %s\n", sentence);
}
else
{
printf("Word not found in sentence.\n");
}
}
}
int identify(char sentence[], char word[])
{
int i, j, k;
for(k = 0; word[k] != '\0'; k++);
{
for(i = 0, j = 0; sentence[i] != '\0'; i++)
{
if(sentence[i] == word[j])
{
j++;
}
else
{
j = 0;
}
}
}
if(j == 1)
{
return(i - j);
}
else
{
return -1;
}
}
int remove(char sentence[], char word[], int deikths)
{
int i, k;
for(k = 0; word[k] != '\0'; k++)
{
for(i = deikths; sentence[i] != '\0'; i++)
{
sentence[i] = sentence[i + k + 1];
}
}
}
The error I am getting, is that the remove function has conflicting types. Any help with fixing my code will be greatly appreciated, or even an alternative solution to my problem would bre great.
As established in the comments, the compiler error is generated because remove is already defined in the stdio.h. After changing, the name the code compiles successfully, but still doesn't work as expected.
identify is the function which is meant to find whether a substring exists in a string and return its position. This is very similar to how strstr from the standard library works - I'd suggest having a look at an implementation of that function, to better understand how this is done.
The function you implemented only correctly finds substrings of length 1, at the end of the string. I have highlighted errors in the code below which cause this.
int identify(char sentence[], char word[])
{
int i, j, k;
for(k = 0; word[k] != '\0'; k++); // <- this loops is never actually ran because of the trailing semicolon - this is however a good thing as it is redundant
{
for(i = 0, j = 0; sentence[i] != '\0'; i++)
{
if(sentence[i] == word[j])
{
j++;
}
else
{
j = 0; // <- this makes it so only matches at the end can be found - otherwise, j is just reset back to 0
}
}
}
if(j == 1) // <- this makes it so only matches of length 1 can be found
{
return(i - j); // <- this is only correct if the match is at the end of the sentence
}
else
{
return -1;
}
}
strremove is inefficient due to the nested loops and the range of characters copied needs to be shortened - right now data is access beyond the end of the array.
int strremove(char sentence[], char word[], int deikths)
{
int i, k;
for(k = 0; word[k] != '\0'; k++) // <- this loop is redundant
{
for(i = deikths; sentence[i] != '\0'; i++) // <- you need to add range checking to make sure sentence[i+k+1] doesn't go beyond the end of the string
{
sentence[i] = sentence[i + k + 1];
}
}
}
I will leave the problems in main as an exercise to you - this is an assignment after all.

Find missing lower-case letters that are not in a series of words

As stated in the title I am trying to find all lower-case letters that are not in a series of words. There are no upper-case letters, digits, punctuation, or special symbols.
I need help fixing my code. I am stuck and do not know where to go from here.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void){
int letters[26];
char words[50];
int i = 0, b = 0;
printf("Enter your input : ");
scanf("%s", words);
for(i = 0; i < 26; i++){
letters[i] = 0;
}
while(!feof(stdin)){
for(b = 0; b < strlen(words) - 1; b++){
letters[ words[b] - 'a']++;
scanf("%s", words);
}
}
printf("\nMissing letters : %c ", b + 97);
return 0;
}
My output is giving me some random letter that I do not know where it is coming from.
Here is a working first implementation.
As well as the comments that have already been made, you should use functions wherever possible to separate out the functionality of the program into logical steps. Your main function should then just call the appropriate functions in order to solve the problem. Each function should be something that is self contained and testable.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_INPUT 20 /* Max input to read from user. */
char *readinput(void);
void find_missing_lower_case(char *, int);
int main()
{
char *user_input = readinput();
int len_input = strlen(user_input);
printf("user input: %s\n", user_input);
printf("len input: %d\n", len_input);
find_missing_lower_case(user_input, len_input);
/* Free the memory allocated for 'user_input'. */
free(user_input);
return 0;
}
char *readinput()
{
char a;
char *result = (char *) malloc(MAX_INPUT);
int i;
for(i = 0; i < MAX_INPUT; ++i)
{
scanf("%c", &a);
if( a == '\n')
{
break;
}
*(result + i) = a;
}
*(result + i) = '\0';
return result;
}
void find_missing_lower_case(char *input, int len_input)
{
int a = 97; /* ASCII value of 'a' */
int z = 122; /* ASCII value of 'z' */
int lower_case_chars[26] = {0}; /* Initialise all to value of 0 */
/* Scan through input and if a lower case char is found, set the
* corresponding index of lower_case_chars to 1
*/
for(int i = 0; i < len_input; i++)
{
char c = *(input + i);
if(c >= a && c <= z)
{
lower_case_chars[c - a] = 1;
}
}
/* Iterate through lower_case_chars and print any values that were not set
* to 1 in the above for loop.
*/
printf("Missing lower case characters:\n");
for(int i = 0; i < 26; i++)
{
if(!lower_case_chars[i])
{
printf("%c ", i + a);
}
}
printf("\n");
}
I figured it out and this is the code I used.
int main(void)
{
int array[26];
char w;
int i=0;
for(i=0; i<26; i++) {
array[i]=0; }
printf("Enter your input: ");
scanf("%c", &w);
while(!feof(stdin)) {
array[w-97] = 1;
scanf("%c", &w); }
printf("Missing letters: ");
for(i=0; i<26; i++) {
if(array[i] == 0) {
printf("%c ", i+97); }
}
printf("\n");
return 0;
}

Arranging a character array using bubble sort

Here is my code so far. I am perfectly able to sort files holding numbers but clueless when it comes to characters. It takes in a file of my choosing and outputs another file with the sorted array. But so far all I'm getting are blank files and I can't figure out why.
So how can I fix my code to sort an array of characters and then output it?
#include <stdio.h>
int bubble_sort(char *a, int n);
int main(void) {
char a[10];
int n = sizeof a / sizeof a[10];
int i;
char inname;
char outname;
printf("Enter input name: ");
scanf("%s", &inname);
printf("Enter output name: ");
scanf("%s", &outname);
FILE *in, *out;
out = fopen(&outname, "w");
if ((in = fopen(&inname, "r")) == NULL) {
printf("File not found\n");
}
else {
for (int i = 0; i < 10; i++)
{
fscanf(in, "%s ", &a[i]);
}
bubble_sort(a, n);
for (i = 0; i < 10; i++) {
printf("%s\n", a[i]);
fprintf(out, "%s\n", a[i]);
}
}
fclose(in);
fclose(out);
return 0;
}
int bubble_sort(char *a, int n) {
int i, j;
char temp;
for (j = 1; j<n; j++)
{
for (i = 0; i<n - j; i++)
{
if ((int)a[i] >= (int)a[i + 1])
{
temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
}
return a[i];
}
The basic problem, as I can see, is with
scanf("%s", &inname);
In your code, inname is a single char, which cannot hold string inputs. You'll be needing an array.
You need to change
char inname;
char outname;
to
#define NAMSIZ 32
char inname[NAMSIZ] = {0};
char outname[NAMSIZ] = {0};
and then,
scanf("%31s", inname);
and accordingly.
Same problem exist with fscanf(in, "%s ", &a[i]);, too.

making a word search puzzle?

I've made a program that allows you to choose the size of the grid and it allows you to enter up to 20 words. Now I have to insert the entered words horizontally into the original array using a function. The function must return a value for success and a value for failure to enter the word into the puzzle board. I need help getting started with what the actual function should look like along with the function prototype. Pseudocode would be helpful. I'm a fairly new programmer so any help is great. Thank you
#include<stdio.h>
#include<string.h>
void printmatrix(char matrix[][20],int);
void inserthor(char matrix[][20],int);
int main(void)
{
//declare variables
char matrix[20][20];
char words[20][100];
int x;
int a,b;
int i=0;
int n=0;
for (a=0;a<20;a++)
{
for (b=0;b<20;b++)
{
matrix[a][b] = '+';
}
}
while (x<10 || x>20)
{
printf("How large would you like the puzzle to be (between 10 and 20):\n");
scanf("%d",&x);
}
printmatrix(matrix,x);
//part 3
printf("Enter up to 20 words to hide in the puzzle.\n");
printf("Enter the word 'done' after your last word if entering less than 20 words.\n");
for (i = 0; i < 20; i++)
{
printf("Enter word %2d:\n", i+1);
if (scanf("%99s", words[i]) != 1 || strcmp(words[i], "done") == 0)
break;
}
n = i;
printf("%d words entered\n", n);
for (i = 0; i < n; i++)
printf("Word %2d = [%s]\n", i+1, words[i]);
return 0;
}
void printmatrix(char matrix[][20],int x)
{
int i,j;
printf("Empty Puzzle:\n");
for (i=0;i<x;i++)
{
for (j=0;j<x;j++)
{
printf(" %c ", matrix[i][j]);
}
printf("\n");
}
}
Your function prototype
void inserthor(char matrix[][20],int);
lacks the parameter with the word to be entered and the value to be returned. You could use
char *inserthor(char matrix[][20], int order, char *word)
{
int i, j, l = strlen(word);
for (i = 0; i < order; ++i)
for (j = 0; j <= order-l; ++j)
if (matrix[i][j] == '+') return memcpy(&matrix[i][j], word, l);
return NULL;
}
which returns the address of the inserted word for success and NULL for failure.

Resources