I want to write a program where it duplicates every letter in a given string.
For example, if the input is abc then the output would be aabbcc.
How can I do this?
Here is my code so far. It only copies the string:
#include <stdio.h>
int main () {
char str_in[100];
char str_out[200] = "";
int i;
printf("Enter a word: ");
scanf("%s", str_in);
for (i = 0; i < sizeof(str_in); i++) {
str_out[i] += str_in[i];
}
printf("Duplicated word: %s", str_out);
return 0;
}
For starters the destination character array should be at least two times larger than the source array.
The loop that performs the copying can look the following way
size_t j = 0;
for ( size_t i = 0; str_in[i] != '\0'; i++ )
{
str_out[j++] = str_in[i];
str_out[j++] = str_in[i];
}
str_out[j] = '\0';
This is one way to do what you want - since you know that the two indexes in str_out that you want to access correspond to the ith and i+1th positions of str_in:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
int main(void)
{
char str_in[SIZE];
char str_out[SIZE*2];
int i, len;
printf("Enter a word: ");
scanf("%s", str_in);
len = strlen(str_in);
for (i = 0; i < len; i++) {
str_out[i*2] = str_in[i];
str_out[i*2+1] = str_in[i];
}
str_out[i*2] = '\0';
printf("Duplicated word: %s\n", str_out);
return EXIT_SUCCESS;
}
You could also use another variable and update inside the loop as such:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
int main(void)
{
char str_in[SIZE];
char str_out[SIZE*2];
int i, j, len;
printf("Enter a word: ");
scanf("%s", str_in);
len = strlen(str_in);
for (i = 0, j = 0; i < len; i++, j += 2) {
str_out[j] = str_in[i];
str_out[j+1] = str_in[i];
}
str_out[j] = '\0';
printf("Duplicated word: %s\n", str_out);
return EXIT_SUCCESS;
}
As a side note, it's best to #define your constants instead of having them in your code.
I would suggest only allocating the amount of memory you need:
char *str_out = malloc(strlen(str_in) + 1);
and then using another loop variable that counts by 2 each time so you have 2 times as much space for every character in your loop.
If you do that, you should also put + 1 next to the new loop variable to copy it to the current and next elements of the string, thereby duplicating the characters.
I would also advise you to use size_t for your loop variables to match the return of str_len.
Here I have implemented my suggestions:
size_t str_ctr;
size_t str_ctrx2;
size_t in_str_len = strlen(in_str)
/* ... */
for( str_ctrx2 = str_ctr = 0;
str_ctr < in_str_len;
str_ctr++, str_ctrx2 += 2 )
{
out_str[str_ctrx2] = in_str[str_ctr];
out_str[str_ctrx2 + 1] = in_str[str_ctr];
}
/* null-terminate the string */
out_str[str_ctrx2] = '\0';
I would also like to mention that you forget to null-terminate your string in your program. I have made a comment about that and have shown you how to do it above.
#include <stdio.h>
int main () {
char str_in[100];
char str_out[200] = "";
int i, j;
printf("Enter a word: ");
scanf("%s", str_in);
j=0;
for (i = 0; i < sizeof(str_in); i++) {
str_out[i] = str_in[j];
str_out[i+1] = str_in[j];
i++;
j++;
}
printf("Duplicated word: %s", str_out);
return 0;
}
Related
My goal is to write a function, that calculates the number of all the unique characters from a redirected text file (meaning until EOF is reached). The code I wrote:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define ASCII_VALS 128
int strLen (char inp[])
{
int len = 0;
for(int i = 0; inp[i] != '\0'; i++){
len++;
}
return len;
}
int countUniqueChars (char inp[])
{
int everyCharValArr[ASCII_VALS] = {0};
int i, j = 0;
for(i = 0; i < strLen(inp); i++){
int convToInt = inp[i] - '0';
everyCharValArr[convToInt] = 1;
}
for (i = 0; i < ASCII_VALS; i++) {
j += everyCharValArr[i];
}
return j;
}
works for one string entered via scanf() like so:
int main ()
{
char inp[100];
printf("Enter a string: \n");
scanf("%99s", inp);
printf("%d\n", countUniqueChars(inp));
return 0;
}
But after I change the main function to read a redirected text file, like so:
int main ()
{
char inp[100];
int total = 0;
while(fgets(inp, 100, stdin)){
total += countUniqueChars(inp);
}
printf("%d\n", total);
return 0;
}
and runinng the program (./binary <input.txt) on a input.txt file with contents below:
Toydolls
Flies
trees
rocks
things
the value becomes 26, which is correct (1. word = 6 unique chars, 2. word = 5 unique chars, 3. word = 4 unique chars, 4. word = 5, 5. word = 6 unique chars), but it obviously does not take into consideration chars that appear on more lines, which should not be counted as unique chars at all. My question is How do I fix the function to accomplish this?
Try something like that: Note that I've added a mechanism not to count a duplicate uppercase letter and its lower case letter as unique.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#define ASCII_VALS 128
int everyCharValArr[ASCII_VALS] = {0};
int strLen (char inp[])
{
int len = 0;
for(int i = 0; inp[i] != '\0'; i++){
len++;
}
return len;
}
void FindUniqueChars (char inp[])
{
int i;
for(i = 0; i < strLen(inp); i++){
if (inp[i] > ' ' && inp[i] != (char)127)
{
if (inp[i] >= 'A' && inp[i] <='Z')
{
inp[i] = tolower(inp[i]);
}
everyCharValArr[(int)inp[i]] = 1;
}
}
}
int CountUniqueChars( void )
{
int i, j = 0;
for (i = 0; i < ASCII_VALS; i++) {
j += everyCharValArr[i];
}
return j;
}
int main ()
{
char inp[100];
while(fgets(inp, 100, stdin)){
FindUniqueChars(inp);
}
printf("%d\n", CountUniqueChars());
return 0;
}
I'm trying to write a program that looks for the first empty space in a 2D array and adds a custom string to that space. I have tried some things that i found on the internet but none seem to work or match my specific scenario. This is it:
#include <stdio.h>
#include <string.h>
int tags[10] = {1,2,3,4,5};
char owners[10][10] = {"per1", "per2", "per3", "per4", "per5"};
int tagAdd;
char ownerAdd;
int i;
int addBool;
int j;
int len;
int main()
{
printf("Enter the tag ID you want to add: ");
scanf("%d", &tagAdd);
printf("Enter the tag owners name: ");
scanf("%d", &ownerAdd);
len = strlen(ownerAdd);
while (i<10)
{
if (tags[i] == 0)
{
tags[i] = tagAdd;
owners[i][len] = ownerAdd; //This is the part I can't figure out
addBool = 1;
}
if (addBool == 1)
{
break;
}
i++;
}
i = 0;
addBool = 0;
len = 0;
while (i<10)
{
printf("tag[%d]", tags[i]);
len = strlen(owners[i]);
printf(" is owned by ");
while (j < len)
{
printf("%c", owners[i][j]);
j++;
}
printf("\n\r");
i++;
j = 0;
}
}
You cannot do this:
char ownerAdd;
scanf("%d", &ownerAdd);
len = strlen(ownerAdd);
You are passing the incorrect types. ownerAdd is a single char, scanf
expects with %d a pointer to int, you are passing a pointer to char and if
scanf converts the value, it will overflow. And strlen expects a char*
which points to a valid string (0-terminated). You are doing all this wrong.
This would be correct:
char ownerAdd[100];
scanf("%99s", ownerAdd);
len = strlen(ownerAdd);
And for replacing a value:
owners[i][len] = ownerAdd; //This is the part I can't figure out
is also wrong, because owners[i] is a char[10], you have to do:
strncpy(owners[i], ownerAdd, sizeof owners[i]);
owners[i][sizeof(owners[i]) - 1] = 0;
to copy the string.
The next error is that you don't initialize i and do (the first loop)
while (i<10)
{
...
}
this is going to fail. Same thing with j, it is uninitialized.
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 am doing this programming problem where I have reverse string of about 30 characters for 10 test cases.
My code is this:-
#include <stdio.h>
#include <string.h>
int main () {
int t;
scanf("%d",&t);
while (t--) {
char str[30];
scanf("%s",&str);
char revStr[30];
int len = strlen(str);
int i = 0;
int j = len-1;
while (i < len) {
revStr[i] = str[j];
i++; j--;
}
printf("%s\n",revStr);
}
return 0;
}
The output gets garbled up if the input string is larger than previous string.
For example,
if last-string had 6 characters, like rocket\0 and new-string, which is fun\0 has 3 characters, the output is funket\0.
char str[30];
scanf("%s",&str);
^ don't pass address of array
Just this would work -
scanf("%29s",str);
Try this:
int t;
scanf("%d", &t);
while (t--)
{
char str[30] = { 0 };
scanf("%s", &str);
char revStr[30] = { 0 };
int len = strlen(str);
int i = 0;
int j = len - 1;
while (i < len) {
revStr[i] = str[j];
i++; j--;
}
printf("%s\n", revStr);
}
You need to make two changes
Firstly change scanf("%s",&str); to
scanf("%s",str);
Secondly, after the while loop, you are not making the last element rev string \0. Add this line before the printf statement.
revStr[i] = '\0';
This should solve your problem.
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
}
}