Hello, let's say I got 2 strings, "Today is a nice day" and "ao". I want to delete the chars of the 2nd string that appear in the 1st one.
This is my issue:
char c[20];
char p[10];
int i,j;
int l1,l2;
printf("Enter a string \n");
scanf("%s",cd);
printf("Enter another string \n");
scanf("%s",car);
len1 = strlen(cd);
len2 = strlen(car);
for (i=0;i<len1;i++){
for (j=0;j<len2;j++){
if (cd[i]==car[j]){
cd[i]="";
}
}
}
What I want is the 1st string to be like "Tdy is nice dy". So I empty the positions where the elements are the same to reposition it later.
Apparently "cd[i]==car[j]" can't be done on C, I got "Invalid conversion from 'const char*' to 'char'.
So i'm pretty much stuck. I'll thank any help.
1) This is a solution matching your algorithm as close as possible.
All what you need is an extra loop and to replace cd[i]=""; which cannot be compiled with cd[i]=0;. The error given by the compiler relates to expression cd[i]=""; cd[i] is a character type and you cannot assign string "" which has a type const char * to char variable. cd[i] is a character "" is a pointer.
The operation cd[i]=0; gives you want you wanted: I empty the positions where the elements are the same to reposition it later. It replaces the unwanted characters with 0.
#include <stdio.h>
#include <string.h>
int main()
{
char cd[] = "Today is a nice day";
char tmp[] = "Today is a nice day";
char car[] = "ao";
int i;
int j;
int k;
int len1 = strlen(cd);
int len2 = strlen(car);
for (i=0;i<len1;i++){
for (j=0;j<len2;j++){
if (cd[i] == car[j]){
cd[i]=0;
}
}
}
k = 0;
for (i=0; i<len1; i++)
{
if(cd[i] == 0)
{
}
else
{
tmp[k] = cd[i];
k++;
}
}
tmp[k] = 0; /* remember to terminate the tmp */
printf("%s\n", tmp);
strcpy(cd,tmp);
printf("%s\n", cd);
return 0;
}
OUTPUT:
Tdy is nice dy
Tdy is nice dy
Alternatively, instead of clearing unwanted character with 0 you could just skip it. This solution is given below:
#include <stdio.h>
#include <string.h>
int main()
{
char cd[] = "Today is a nice day";
char car[] = "ao";
int i;
int j;
int k = 0;
int skip = 0;
int len1 = strlen(cd);
int len2 = strlen(car);
for (i=0; i<len1; i++)
{
for (j=0; j<len2; j++)
{
if (cd[i] == car[j])
{
skip++; // make note that this character is not needed
}
}
if(skip == 0)
{
cd[k] = cd[i]; // copy the character
k++; // increase the position index
}
else
{
// skip the copy of charcter; clear the skip marker
skip = 0;
}
}
cd[k] = 0; // remember to terminate the new ck string!
printf("%s\n", cd);
return 0;
}
OUTPUT:
Tdy is nice dy
Related
I am trying to write a program that encrypts whatever the user types according to an encryption alphabet. However, when printing out the result, I keep getting one extra random character at the end of my result string. I have tried to end my result string with an '\0' but it doesn't work. Please send some help!
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int find_index(char a[], int num_elements, char value);
int main (void)
{
string ori = "abcdefghijklmnopqrstuvwxyz"; // original alphabet
string key = "ZYXWVUTSRQPONMLKJIHGFEDCBA"; // encryption alphabet
string plain_text = get_string("plaintext: ");
// count the number of characters in plain_text
int count = 0;
for (int i = 0; plain_text[i] != '\0'; i++)
{
count++;
}
char answer [count + 1];
answer[count+1] = '\0';
for (int i = 0; i < count ; i++)
{
// if the character is not in alphabet, just add it to answer
if (isalpha(plain_text[i]) == false)
{
answer[i] = plain_text[i];
}
else
{
// take the original character in plain text
char ori_char = plain_text[i];
// find it index in the orginal alphabet
int index_ori = find_index(ori, 26, tolower(ori_char));
// find the corresponding character in encryption alphabet
char res_char = key[index_ori];
if islower(ori_char)
{
res_char = tolower(res_char);
}
else
{
res_char = toupper(res_char);
}
// update the char list
answer[i] = res_char;
}
}
printf ("ciphertext: %s\n", answer);
}
int find_index(string a, int num_elements, char value) // find index of a character in a string
{
int x = -1;
for (int i=0; i < num_elements; i++)
{
if (a[i] == value)
{
x = i;
return x;
}
}
return(x); /* if it was not found */
}
char answer [count + 1]; answer[count+1] = '\0'; is UB as it attempts to access outside the array.
Perhaps other problems too.
I got given this assignment:
Write a C program that sequentially writes two strings into each other as shown in the figure below. Start with a string
consisting of “X”-es and with each iteration, the first and last X characters must be rewritten until the entire string is
rewritten and the final message is displayed.
Hint: Make use a function in the library, strlen(), to determine the length of a string.
It should output like this:
XXXXXXXXXXXXXXXXXXXXX
IXXXXXXXXXXXXXXXXXXX!
I XXXXXXXXXXXXXXXXXg!
I lXXXXXXXXXXXXXXXng!
I loXXXXXXXXXXXXXing!
I lovXXXXXXXXXXXming!
I loveXXXXXXXXXmming!
I love XXXXXXXamming!
I love CXXXXXramming!
I love C-XXXgramming!
I love C-PXogramming!
I love C-Programming!
Final String= I love C-Programming!
This is what I have so far:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
//data
char str[] = "I love C-Programming!";
int rows;
int columns;
int length = strlen(str);
int format =5;
//process
{
rows = 0;
while (rows <= length)
{
rows++;
}
while (rows > 0)
{
int count = length;
columns = rows - 1;
while (columns > 0)
{
printf("X");
columns--;
count --;
}
if (rows <= length)
{
printf("%.*s", count, str);
}
printf("\n");
rows-=2;
}
printf("%s", str);
}
//output
printf("\n");
printf("\n");
printf("Final String = %s\n", str);
return 0;
}
It doesn't display properly. Please help!
Thanks.
#include <stdio.h>
#include <string.h>
int main()
{
char s1[] = "XXXXXXXXXXXXXXXXXXXXX";
const char s2[] = "I love C-Programming!";
const int n = strlen(s1);
const int h = n / 2;
int i;
int j;
puts(s1);
for (i = 0, j = n - 1; i <= h; ++i, --j) {
s1[i] = s2[i];
s1[j] = s2[j];
puts(s1);
}
return 0;
}
Hi this is indeed a very simple program. Actually your teacher want you to write a program like below:-
int main(int argc, char **argv)
{
//data
char str1[] = "I love C-Programming!";
char str2[strlen(str1)];
memset(str2, 'X', sizeof(str2));//Set all the character to X
str2[strlen(str1)-1]=0;//end of string character value of '\0'
//int rows;
//int columns;
int length = strlen(str1);
//int format =5;
int i = 0;
int j = length - 1;
do
{
printf("%s\n", str2);//Print the second string first
str2[i]=str1[i];//copy from first character from str1
str2[j]=str1[j];//copy from last character from str1
//so in each iteration we are coping two characters from str1 to str2
}while(i++ != j-- );//once I and j are equal break the loop
printf("%s", str2);
/*
//process
{
rows = 0;
while (rows <= length)
{
rows++;
}
while (rows > 0)
{
int count = length;
columns = rows - 1;
while (columns > 0)
{
printf("X");
columns--;
count --;
}
if (rows <= length)
{
printf("%.*s", count, str);
}
printf("\n");
rows-=2;
}
printf("%s", str);
}
*/
//output
printf("\n");
printf("\n");
printf("Final String = %s\n", str2);
return 0;
}
It will out put like below:-
XXXXXXXXXXXXXXXXXXXX
IXXXXXXXXXXXXXXXXXXX!
I XXXXXXXXXXXXXXXXXg!
I lXXXXXXXXXXXXXXXng!
I loXXXXXXXXXXXXXing!
I lovXXXXXXXXXXXming!
I loveXXXXXXXXXmming!
I love XXXXXXXamming!
I love CXXXXXramming!
I love C-XXXgramming!
I love C-PXogramming!
I love C-Programming!
Final String = I love C-Programming!
So I have an assignment where I should delete a character if it has duplicates in a string. Right now it does that but also prints out trash values at the end. Im not sure why it does that, so any help would be nice.
Also im not sure how I should print out the length of the new string.
This is my main.c file:
#include <stdio.h>
#include <string.h>
#include "functions.h"
int main() {
char string[256];
int length;
printf("Enter char array size of string(counting with backslash 0): \n");
/*
Example: The word aabc will get a size of 5.
a = 0
a = 1
b = 2
c = 3
/0 = 4
Total 5 slots to allocate */
scanf("%d", &length);
printf("Enter string you wish to remove duplicates from: \n");
for (int i = 0; i < length; i++)
{
scanf("%c", &string[i]);
}
deleteDuplicates(string, length);
//String output after removing duplicates. Prints out trash values!
for (int i = 0; i < length; i++) {
printf("%c", string[i]);
}
//Length of new string. The length is also wrong!
printf("\tLength: %d\n", length);
printf("\n\n");
getchar();
return 0;
}
The output from the printf("%c", string[i]); prints out trash values at the end of the string which is not correct.
The deleteDuplicates function looks like this in the functions.c file:
void deleteDuplicates(char string[], int length)
{
for (int i = 0; i < length; i++)
{
for (int j = i + 1; j < length;)
{
if (string[j] == string[i])
{
for (int k = j; k < length; k++)
{
string[k] = string[k + 1];
}
length--;
}
else
{
j++;
}
}
}
}
There is a more efficent and secure way to do the exercise:
#include <stdio.h>
#include <string.h>
void deleteDuplicates(char string[], int *length)
{
int p = 1; //current
int f = 0; //flag found
for (int i = 1; i < *length; i++)
{
f = 0;
for (int j = 0; j < i; j++)
{
if (string[j] == string[i])
{
f = 1;
break;
}
}
if (!f)
string[p++] = string[i];
}
string[p] = '\0';
*length = p;
}
int main() {
char aux[100] = "asdñkzzcvjhasdkljjh";
int l = strlen(aux);
deleteDuplicates(aux, &l);
printf("result: %s -> %d", aux, l);
}
You can see the results here:
http://codepad.org/wECjIonL
Or even a more refined way can be found here:
http://codepad.org/BXksElIG
Functions in C are pass by value by default, not pass by reference. So your deleteDuplicates function is not modifying the length in your main function. If you modify your function to pass by reference, your length will be modified.
Here's an example using your code.
The function call would be:
deleteDuplicates(string, &length);
The function would be:
void deleteDuplicates(char string[], int *length)
{
for (int i = 0; i < *length; i++)
{
for (int j = i + 1; j < *length;)
{
if (string[j] == string[i])
{
for (int k = j; k < *length; k++)
{
string[k] = string[k + 1];
}
*length--;
}
else
{
j++;
}
}
}
}
You can achieve an O(n) solution by hashing the characters in an array.
However, the other answers posted will help you solve your current problem in your code. I decided to show you a more efficient way to do this.
You can create a hash array like this:
int hashing[256] = {0};
Which sets all the values to be 0 in the array. Then you can check if the slot has a 0, which means that the character has not been visited. Everytime 0 is found, add the character to the string, and mark that slot as 1. This guarantees that no duplicate characters can be added, as they are only added if a 0 is found.
This is a common algorithm that is used everywhere, and it will help make your code more efficient.
Also it is better to use fgets for reading input from user, instead of scanf().
Here is some modified code I wrote a while ago which shows this idea of hashing:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define NUMCHAR 256
char *remove_dups(char *string);
int main(void) {
char string[NUMCHAR], temp;
char *result;
size_t len, i;
int ch;
printf("Enter char array size of string(counting with backslash 0): \n");
if (scanf("%zu", &len) != 1) {
printf("invalid length entered\n");
exit(EXIT_FAILURE);
}
ch = getchar();
while (ch != '\n' && ch != EOF);
if (len >= NUMCHAR) {
printf("Length specified is longer than buffer size of %d\n", NUMCHAR);
exit(EXIT_FAILURE);
}
printf("Enter string you wish to remove duplicates from: \n");
for (i = 0; i < len; i++) {
if (scanf("%c", &temp) != 1) {
printf("invalid character entered\n");
exit(EXIT_FAILURE);
}
if (isspace(temp)) {
break;
}
string[i] = temp;
}
string[i] = '\0';
printf("Original string: %s Length: %zu\n", string, strlen(string));
result = remove_dups(string);
printf("Duplicates removed: %s Length: %zu\n", result, strlen(result));
return 0;
}
char *remove_dups(char *str) {
int hash[NUMCHAR] = {0};
size_t count = 0, i;
char temp;
for (i = 0; str[i]; i++) {
temp = str[i];
if (hash[(unsigned char)temp] == 0) {
hash[(unsigned char)temp] = 1;
str[count++] = str[i];
}
}
str[count] = '\0';
return str;
}
Example input:
Enter char array size of string(counting with backslash 0):
20
Enter string you wish to remove duplicates from:
hellotherefriend
Output:
Original string: hellotherefriend Length: 16
Duplicates removed: helotrfind Length: 10
I'm parsing a text file:
Hello, this is a text file.
and creating by turning the file into a char[]. Now I want to take the array, iterate through it, and create an array of arrays that splits the file into words:
string[0] = Hello
string[1] = this
string[2] = is
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "TextReader.h"
#include <ctype.h>
void printWord(char *string) {
int i;
for (i = 0; i < strlen(string); i ++)
printf("%c", string[i]);
printf("\n");
}
void getWord(char *string) {
char sentences[5][4];
int i;
int letter_counter = 0;
int word_counter = 0;
for (i = 0; i < strlen(string); i ++) {
// Checks if the character is a letter
if (isalpha(string[i])) {
sentences[word_counter][letter_counter] = string[i];
letter_counter++;
} else {
sentences[word_counter][letter_counter + 1] = '\0';
word_counter++;
letter_counter = 0;
}
}
// This is the code to see what it returns:
i = 0;
for (i; i < 5; i ++) {
int a = 0;
for (a; a < 4; a++) {
printf("%c", sentences[i][a]);
}
printf("\n");
}
}
int main() {
// This just returns the character array. No errors or problems here.
char *string = readFile("test.txt");
getWord(string);
return 0;
}
This is what it returns:
Hell
o
this
is
a) w
I suspect this has something to do with pointers and stuff. I come from a strong Java background so I'm still getting used to C.
With sentences[5][4] you're limiting the number of sentences to 5 and the length of each word to 4. You'll need to make it bigger in order to process more and longer words. Try sentences[10][10]. You're also not checking if your input words aren't longer than what sentences can handle. With bigger inputs this can lead to heap-overflows & acces violations, remember that C does not check your pointers for you!
Of course, if you're going to use this method for bigger files with bigger words you'll need to make it bigger or allocate it dymanically.
sample that do not use strtok:
void getWord(char *string){
char buff[32];
int letter_counter = 0;
int word_counter = 0;
int i=0;
char ch;
while(!isalpha(string[i]))++i;//skip
while(ch=string[i]){
if(isalpha(ch)){
buff[letter_counter++] = ch;
++i;
} else {
buff[letter_counter] = '\0';
printf("string[%d] = %s\n", word_counter++, buff);//copy to dynamic allocate array
letter_counter = 0;
while(string[++i] && !isalpha(string[i]));//skip
}
}
}
use strtok version:
void getWord(const char *string){
char buff[1024];//Unnecessary if possible change
char *p;
int word_counter = 0;
strcpy(buff, string);
for(p=buff;NULL!=(p=strtok(p, " ,."));p=NULL){//delimiter != (not isaplha(ch))
printf("string[%d] = %s\n", word_counter++, p);//copy to dynamic allocate array
}
}
i'm developing a little function to display the most frequent character in a (char) array.
This is what I've accomplished so far, but I think i'm on the wrong way.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char test[10] = "ciaociaoci";
max_caratt(test, 10);
}
int max_caratt(char input[], int size)
{
int i;
char max[300];
max[0] = input[0];
for (i=0; i<size; i++)
{
if(strncmp(input,input[i],1) == 1)
{
printf("occourrence found");
max[i] = input[i];
}
}
}
Any help?
Actually, the correct code is this.
It's just a corrected version of IntermediateHacker's below snippet.
void main()
{
int array[255] = {0}; // initialize all elements to 0
char str[] = "thequickbrownfoxjumpedoverthelazydog";
int i, max, index;
for(i = 0; str[i] != 0; i++)
{
++array[str[i]];
}
// Find the letter that was used the most
max = array[0];
index = 0;
for(i = 0; str[i] != 0; i++)
{
if( array[str[i]] > max)
{
max = array[str[i]];
index = i;
}
}
printf("The max character is: %c \n", str[index]);
}
The easiest way to find the most common character is to create an int array of 255 and just increment the arraly element that corresponds to the character. For example: if the charcter is 'A', then increment the 'A'th element (if you look at any ascii table you will see that the letter 'A' has a decimal value of 65)
int array[255] = {0}; // initialize all elements to 0
char str[] = "The quick brown fox jumped over the lazy dog.";
int i, max, index;
// Now count all the letters in the sentence
for(i = 0; str[i] != 0; i++)
{
++array[str[i]];
}
// Find the letter that was used the most
max = array[0];
index = 0;
for(i = 0; str[i] != 0; i++)
{
if( array[i] > max)
{
max = array[i];
index = i;
}
}
printf("The max character is: %c \n", (char)index);
You're passing a (almost) string and a char to strncmp(). strncmp() takes two strings (and an integer). Your program shouldn't even compile!
Suggestion: increase the warning level of your compiler and mind the warnings.
You may want to look at strchr() ...
Assuming an input array of 0-127, the following should get you the most common character in a single pass through the string. Note, if you want to worry about negative numbers, shift everything up by +127 as needed...
char mostCommonChar(char *str) {
/* we are making the assumption that the string passed in has values
* between 0 and 127.
*/
int cnt[128], max = 0;
char *idx = str;
/* clear counts */
memset((void *)cnt, 0, sizeof(int) * 128);
/* collect info */
while(*idx) {
cnt[*idx]++;
if(cnt[*idx] > cnt[max]) {
max = *idx;
}
idx++;
}
/* we know the max */
return max;
}
If you don't need to preserve the input array, you could sort the input array first, then find the longest contiguous run of a single character. This approach is slower, but uses less space.
I made a working version using structs. It works fine, I guess, but I think there's a MUCH better way to write this algorithm.
#include <stdio.h>
#include <stdlib.h>
struct alphabet {
char letter;
int times;
};
typedef struct alphabet Alphabet;
void main() {
char string[300];
gets(string);
Alphabet Alph[300];
int i=0, j=0;
while (i<=strlen(string)) {
while(j<=300) {
if(string[i] != Alph[j].letter) {
Alph[i].letter = string[i];
Alph[i].times = 1;
}
else {
Alph[j].times++;
}
j++;
}
j=0;
i++;
}
int y,max=0;
char letter_max[0];
for (y=0; y<strlen(string); y++) {
printf("Letter: %c, Times: %d \n", Alph[y].letter, Alph[y].times);
if(Alph[y].times>max) {
max=Alph[y].times;
letter_max[0]=Alph[y].letter;
}
}
printf("\n\n\t\tMost frequent letter: %c - %d times \n\n", letter_max[0], max);
}
I saw you all creating big arrays and "complex" stuff so here I have easy and simple code xD
char most_used_char (char s[]) {
int i; //array's index
int v; //auxiliary index for counting characters
char c_aux; //auxiliary character
int sum = 0; //auxiliary character's occurrence
char c_max; //most used character
int max = 0; //most used character's occurrence
for (i = 0; s[i]; i++) {
c_aux = s[i];
for (v = 0; s[v]; v++)
if (c_aux == s[v]) sum++; /* responsible cycle for counting
character occurrence */
if (sum > max) { //checks if new character is the most used
max = sum;
c_max = c_aux;
}
sum = 0; /* reset counting variable so it can counts new
characters occurrence */
}
return c_max; //this is the most used character!
}