this is my first post in this forum so please be patient.
I need to make a short programm, where the user can enter 2 strings which should be attached afterwards.
I already got this code below (I am not allowed to use other "includes").
What I need to know is: How can I deny any spaces which the user will enter?
Example: 1. String "Hello " | 2. String "World" Result should be "HelloWorld" instead of "Hello World".
#include <stdio.h>
void main()
{
char eingabe1[100];
char eingabe2[100];
int i = 0;
int j = 0;
printf("Gib zwei Wörter ein, die aneinander angehängt werden sollen\n");
printf("1. Zeichenkette: ");
gets(eingabe1);
printf("\n");
printf("2. Zeichenkette: ");
gets(eingabe2);
printf("\n");
while (eingabe1[i] != '\0')
{
i++;
}
while (eingabe2[j] != '\0')
{
eingabe1[i++] = eingabe2[j++];
}
eingabe1[i] = '\0';
printf("Nach Verketten: ");
puts(eingabe1);
}
You have to filter out the spaces as you copy your strings.
You have two string indices, i for the first string and and j for the second string. You could make better use of these indices if you used i for the reading position (of both strings subsequently; you can "reuse" loop counters in independent loops) and j for the writing position.
Here's how. Note that the code attempts to prevent buffer overflow by only adding characters if there is space in the string. This check needs only to be done when copying the second string, because j <= i when you process the first string.
#include <stdio.h>
int main()
{
char str1[100] = "The quick brown fox jumps over ";
char str2[100] = "my big sphinx of quartz";
int i = 0;
int j = 0;
while (str1[i] != '\0') {
if (str1[i] != ' ') str1[j++] = str1[i];
i++;
}
i = 0;
while (str2[i] != '\0') {
if (str2[i] != ' ' && j + 1 < sizeof(str1)) str1[j++] = str2[i];
i++;
}
str1[j] = '\0';
printf("'%s'\n", str1);
return 0;
}
In addition to avoiding spaces between your two words, you also have to avoid the newline ('\n') character placed in the input buffer by the user pressing Enter. You can do that with a simple test after you have read the line with fgets() NOT gets(). gets() is no longer part of the standard C library and should not be used due to insecurity reasons. Plus fgets provides simple length control over the number of characters a user may enter at any time.
Below, you run into trouble when you read eingabe1. After the read, eingabe1 contains a '\n' character at its end. (as it would using any of the line-oriented input functions (e.g. getline(), fgets(), etc) To handle the newline, you can simply compare its length minus '1' after you loop over the string to find the nul character. e.g.:
if (eingabe1[i-1] == '\n') i--; /* remove trailing '\n', update i */
By simply reducing the index 'i', this will guarantee that the concatenation with eingabe2 will not have any spaces or newline characters between the words.
Putting the pieces together, and using fgets in place of the insecure gets, after #define MAX 100'ing a constant to prevent hardcoding your array indexes, you could come up with something similar to:
#include <stdio.h>
#define MAX 100
int main (void)
{
char eingabe1[MAX] = {0};
char eingabe2[MAX] = {0};
int i = 0;
int j = 0;
printf("Gib zwei Wörter ein, die aneinander angehängt werden sollen\n");
printf("1. Zeichenkette: ");
/* do NOT use gets - it is no longer part of the C library */
fgets(eingabe1, MAX, stdin);
putchar ('\n');
printf("2. Zeichenkette: ");
/* do NOT use gets - it is no longer part of the C library */
fgets(eingabe2, MAX, stdin);
putchar ('\n');
while (eingabe1[i]) i++; /* set i (index) to terminating nul */
if (i > 0) {
if (eingabe1[i-1] == '\n') i--; /* remove trailing '\n' */
while (i && eingabe1[i-1] == ' ') /* remove trailing ' ' */
i--;
}
while (eingabe2[j]) { /* concatenate string - no spaces */
eingabe1[i++] = eingabe2[j++];
}
eingabe1[i] = 0; /* nul-terminate eingabe1 */
printf("Nach Verketten: %s\n", eingabe1);
return 0;
}
Output
$ ./bin/strcatsimple
Gib zwei Wörter ein, die aneinander angehängt werden sollen
1. Zeichenkette: Lars
2. Zeichenkette: Kenitsche
Nach Verketten: LarsKenitsche
Let me know if you have any further questions. I have highlighted the changes with comments above.
/**
return: the new len of the string;
*/
int removeChar(char* string, char c) {
int i, j;
int len = strlen(string)+1; // +1 to include '\0'
for(i = 0, j = 0 ; i < len ; i++){
if( string[i] == c )
continue; // avoid incrementing j and copying c
string[ j ] = string[ i ]; // shift characters
j++;
}
return j-1; // do not count '\0';
}
int main(){
char str1[] = "sky is flat ";
char str2[100] = "earth is small ";
strcat( str2, str1 );
printf("with spaces:\n\t'%s'\n", str2) ;
removeChar(str2, ' ');
printf("without spaces:\n\t'%s'\n", str2 );
}
/**
BONUS: this will remove many characters at once, eg "\n \r\t"
return: the new len of the string;
*/
int removeChars(char* string, char *chars) {
int i, j;
int len = strlen(string);
for(i = 0, j = 0 ; i < len ; i++){
if( strchr(chars,string[i]) )
continue; // avoid incrementing j and copying c
string[ j ] = string[ i ]; // shift characters
j++;
}
string[ j ]=0;
return j;
}
Thank you everyone for all the answers.
I got the solution now.
I read some advices from you and will try to remember for the future.
See the code below:
(Excuse me for the strange names for the variables, I use german words)
A few notices:
I am not allowed to use library functions
I am not allowed to use fgets for some reasons as a trainee
#include <stdio.h>
void main()
{
char eingabe1[100];
char eingabe2[100];
int i = 0;
int j = 0;
printf("gib zwei wörter ein, die aneinander angehängt werden sollen\n");
printf("1. zeichenkette: ");
gets(eingabe1);
printf("\n");
printf("2. zeichenkette: ");
gets(eingabe2);
printf("\n");
//Attach Strings
while (eingabe1[i] != '\0')
{
i++;
}
while (eingabe2[j] != '\0')
{
eingabe1[i++] = eingabe2[j++];
}
//Remove Space
eingabe1[i] = '\0';
i = 0;
j = 0;
while (eingabe1[i] != '\0')
{
if (eingabe1[i] != 32)
{
eingabe2[j++] = eingabe1[i];
}
i++;
}
eingabe2[j] = '\0';
printf("Nach verketten: ");
puts(eingabe2);
}
Sounds like homework to me.
I just wanted to mention that you probably shouldn't use sizeof() on strings these days because there may be multibyte characters in there. Use strlen() instead. The only time sizeof() would be appropriate is if you're going to malloc() a certain number of bytes to store it.
I write little loops fairly often to do low level text stuff one character at a time, just be aware that strings in C usually have a 0 byte at the end. You have to expect to encounter one and be sure you put one on the output. Space is 0x20 or decimal 32 or ' ', it's just another character.
Related
I wrote a program to find the longest word in a string and print the number of letters in the longest word. But the code is not printing. I analyzed the program many times but I could not find the solution.
#include <stdio.h>
#include <string.h>
int main() {
char string[100] = "Hello Kurnool";
int i = 0, letters = 0, longest = 0;
start:
for (; string[i] !=' '; i++) {
letters++;
}
if (letters >= longest)
longest = letters;
if (string[i] == ' ') {
letters = 0;
i++;
goto start;
}
printf("%d", longest);
return 0;
}
Using goto is highly discouraged. You should convert your code to use a loop.
The main problem in your code is you do not stop the scan when you reach the end of the string.
Here is a modified version:
#include <stdio.h>
int main() {
char string[100] = "Hello Kurnool";
int i, letters, longest = 0, longest_pos = 0;
for (i = 0; string[i] != '\0'; i++) {
for (letters = 0; string[i] != '\0' && string[i] != ' '; i++) {
letters++;
}
if (letters > longest) {
longest = letters;
longest_pos = i - longest;
}
}
printf("longest word: %d letters, '%.*s'\n",
longest, longest, string + longest_pos);
return 0;
}
Note that the implementation can be simplified into a single loop:
#include <stdio.h>
int main() {
char string[100] = "Hello Kurnool";
int i, start = 0, longest = 0, longest_pos = 0;
for (i = 0; string[i] != '\0'; i++) {
if (string[i] == ' ') {
start = i + 1;
} else {
if (i - start > longest) {
longest = i - start;
longest_pos = start;
}
}
}
printf("longest word: %d letters, '%.*s'\n",
longest, longest, string + longest_pos);
return 0;
}
Below is my approach. You should use C's string manipulation functions. This is the correct way to deal with strings in C.
In the code below, first I acquire the required bytes to store the input string in heap. Then I use strtok to split the string into tokens based on a delemeter and get the length of each sub string. Finally I free the space that I have allocated with malloc.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define phrase "Hello Kurnool"
int main()
{
char* string = malloc(strlen(phrase)+1);
strcpy(string,phrase);
int longest=0;
char *token;
char delimeter[2] = " ";
/* get the first token */
token = strtok(string, delimeter);
/* walk through other tokens */
while( token != NULL ) {
printf( " %s\n", token );
if(longest < strlen(token)){
longest = strlen(token);
}
token = strtok(NULL, delimeter);
}
printf("%d",longest);
free(string);
return 0;
}
People say - dont use goto but there is nothing inherently wrong with goto. Only thing is if goto is not used judiciously, it makes code more difficult to understand and maintain. For example, the way you have used it in your program ( instead of goto, a loop is perfect fit in such cases). Check this:
To use goto or not?
What is wrong with using goto?
Coming to your code, the for loop condition does not have check for terminating null character
for (; string[i] !=' '; i++) {
Hence it will not stop at the end of string.
To find the number of letters in longest word of string, you can do:
#include <stdio.h>
#include <string.h>
int main() {
char string[100] = "Hello Kurnool";
int i, letters = 0, longest = 0;
for (i = 0; string[i] != '\0'; i++) {
if (string[i] != ' ') {
letters++;
if (letters > longest) {
longest = letters;
}
} else {
letters = 0;
}
}
printf("longest : %d\n", longest);
return 0;
}
First of all,Please avoid using Goto, it is not a good practice.
Secondly, your loop will run infinite times when it iterates the second time because:
for(;string[i]!=' ';i++) // Here String[i] will never be equal to ' ' As there is no white space after your last word.
You can never expect what might be going wrong with your program if you are using
goto statement
which is never advisable to use rather it's bad programming if you use it. Secondly it looks like you are stuck in an infinite loop so her is a solution to your problem:
#include<stdio.h>
#include<string.h>
void main()
{
char s[1000];
scanf("%s",s);
int i=0;
int letters;
int longest=0;
while(s[i]!=NULL)
{
if(s[i]==' ')
{
if(longest>=letters)
{longest=letters;}
letters=0;
}
else
{letters++;}
}
printf("%d\n",longest);
}
So, what I have done is assuming a string s which is the input given by the user. You itterate through s till the last input given by the user after which it encounters a NULL character. Now you are searching for the length of the longest word, so you create a variable letters for counting the no. of letters in each word of the string. And if the string s encounters a space indicating the end of a word, then you check if the variable longest is greater than or less than the word count. And again you initialize letters to 0, so that it can start counting the next word from 0 again.So, by this method at the end i.e. after the while loop terminates we get our required output which is stored in the variable longest.
So, I guess this will print the no. of letters in the longest word.
I'm relatively new to coding array functions in C. After numerous tries, I've decided to surrender and ask for help.
I wish to the user to input the words and store them into the 2d array words. The problem is that it prints the words but also prints out random characters.
#include "mp1_lib.h"
void get_words(int n, char words[][16])
{
char c = ' ';
char check;
for(int x=0; x <= n; x++)
{
for(int y=0; y < 16; y++)
{
c = getchar();
check = c;
if (check == '\n')
{
break;
}
words[x][y] = c;
}
}
}
void print_words(int n, char words[][16])
{
for(int x=1; x <= n; x++)
{
for(int y=0; y < 16; y++)
{
if (words[x][y] == '\n')
{
break;
}
putchar(words[x][y]);
}
printf("\n");
}
}
In C, a string is an array of characters with the nul-terminating character '\0' as the character that marks the end of the contents of the string within the array. That is how all string functions like strlen or printf using the '%s' format specifier to print a string -- know where the string stops.
If you do not nul-terminate the array of characters -- then it is not a string, it is simply an array and you cannot pass an un-terminate array to any function expecting a string - or it won't know where the string ends (and in the case of printf will just print whatever unspecified character happens to be in memory until it comes upon a '\0' to stop the output (or SegFaults).
If you don't nul-terminate the words in your array, then you will have to have some way to store the number of characters in each word, so your print function will know where to stop printing. (if you have a two-letter word like "Hi" in a 16-char array, you can only print 2 characters from the array. Especially if it is an uninitialized array, then you will simply get gibberish printed for characters 3-16.
Your second problem is -- "How do you know how many words you have stored in your array?" -- you don't return a value from getwords, so unless you change the function type to int and return the number of words that you stored in your array, your only other option is to pass a pointer to an integer and update the value at that address so the value is available back in the calling function. Either way is fine, you generally only worry about making a value available through a pointer if you are already returning another value and need a second method to make another updated value visible back in the calling function (main() here).
Putting those pieces together, and passing a pointer to the number of words to getwords to make the number of words entered available back in main() (so you know how many words print_words has to print), you could do something similar to the following:
#include <stdio.h>
#include <ctype.h>
#define MAXC 16 /* if you need constants, define them */
#define MAXW 32
void getwords (char (*words)[MAXC], int *n)
{
int col = 0; /* column count */
while (*n < MAXW) { /* while words < MAXW */
int c = getchar(); /* read char */
/* column reaches MAXC-1 or if whitespace or EOF */
if (col == MAXC - 1 || isspace(c) || c == EOF) {
if (col) { /* if col > 0 */
words[(*n)++][col] = 0; /* nul-terminate, increment n */
col = 0; /* set col to zero */
}
if (c == EOF) /* if char EOF - all done */
return;
}
else /* otherwise - just add char to word */
words[*n][col++] = c;
}
}
void prnwords (char (*words)[MAXC], int n)
{
for (int i = 0; i < n; i++) /* loop over each of n-words & print */
printf ("words[%2d]: %s\n", i, words[i]);
}
int main (void) {
char words[MAXW][MAXC] = {""}; /* intiliaze words all zero */
int nwords = 0; /* number of words zero */
getwords (words, &nwords);
prnwords (words, nwords);
return 0;
}
(note: when reading characters into the words array, you must check the number of character read again the maximum characters per-word (MAXC) and the number of words against the maximum number of words/rows in your array (MAXW) to prevent writing outside of your array bounds -- which will invoke Undefined Behavior in your program)
(note: the ctype.h header was included to simplify checking whether the character read was whitespace (e.g. a space, tab, or newline). If you can't use it, then simply use an if (c == ' ' || c == '\t' || c == '\n') instead.)
Example Use/Output
$ echo "my dog has fleas and my cat has none" | ./bin/getwords
words[ 0]: my
words[ 1]: dog
words[ 2]: has
words[ 3]: fleas
words[ 4]: and
words[ 5]: my
words[ 6]: cat
words[ 7]: has
words[ 8]: none
Not too familiar with c. But it appears like you are not addding the new line character to the words array in get_words.
check = c;
if (check == '\n')
{
break;
}
words[x][y] = c;
So when printing in print_words this will never be true.
if (words[x][y] == '\n')
{
break;
}
That means that whatever happens to be in the memory location is what will get printed.
Your words have neither the newline character (which makes your code print garbage) nor the terminating NULLs (which makes them illegal as C strings). At least add words[x][y]="\n" before breaking the inner loop. Or, rather, move the if check after the assignment words[x][y]=c;. And yes, the loop should go from 0 to n-1.
As a side note, you do not need the variable check: just use c.
I tried to assign space as a placeholder for the 15 characters and it worked. Thanks, everyone! :)
#include "mp1_lib.h"
void get_words(int n, char words[][16])
{
char c = ' ';
char check;
for(int x=0; x < n; x++)
{
for(int y=0; y < 16; y++)
{
words[x][y] = ' ';
}
}
for(int x=0; x < n; x++)
{
for(int y=0; y < 16; y++)
{
c = getchar();
check = c;
if (check == '\n')
{
break;
}
words[x][y] = c;
}
}
}
void print_words(int n, char words[][16])
{
for(int x=0; x < n; x++)
{
for(int y=0; y < 16; y++)
{
putchar(words[x][y]);
}
printf("\n");
}
}
The issue is detecting '\n' when I loop through my array. It works once as
shown in the comments, but it does not work after. The goal of this program is to take input from the terminal and put it into an array. The array should not contain any '\n'. Any help is appreciated, Thanks
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// 1. Function must take input and place in array whilst making sure it does not overflow
// 2. Must return null if end of stdi is reached
// 3. Must ensure that it does not contain delimeter \n
// Tests:
// a) empty string
// b) string longer than buffer
// c) what happens when you press ctrl-d
char read_line(char *buf, size_t sz) {
while(fgets(buf + strlen(buf), sz, stdin)){
if (strlen(buf) < sz) {
if(buf[strlen(buf)-1] == '\n' ){
// IT GET'S DETECTED HERE WHEN THE ENTER
// BUTTON
// IS PRESSED BUT ...
break;
}
}
}
// WHEN I LOOP THROUGH THE ARRAY IT GETS DETECTED AS SINGLE CHARS; '\'
// AND 'n' DISTINCTLY
for(int i = 0; i < strlen(buf)-1; ++i){
if(buf[i] == '\n'){
printf("present");
} else {
printf("x");
}
}
return NULL;
}
int main(int argc, char *argv[]){
char arra[20];
size_t sz = sizeof(arra);
memset(arra, 0, sz);
printf("Enter command: \n");
read_line(arra, sz);
// Print elements in array
printf("Printing out array: \n");
for(int i = 0; i < strlen(arra); ++i){
char c = arra[i];
printf("%c", c);
}
}
You appear to be entering something like the keystrokes hello\nENTER.
The entry of the two distinct characters \ and n are exactly that, two distinct characters. That is vastly different to the single newline character which is represented in the source as \n.
In terms of what the buffer will hold, it'll be the string "hello\\n\n", where \\ is the \ character, n is an n, and \n is the newline.
If your intent is to detect the newline in the string, you'll need to process every character in the string. The loop:
for (int i = 0; i < strlen(buf) - 1; ++i) ...
will basically skip the last character, which is fine for ignoring trailing newline should it exist but, if you want to detect it, you'll need:
for (int i = 0; i < strlen(buf); ++i) ...
suggest replacing:
for(int i = 0; i < strlen(buf)-1; ++i){
if(buf[i] == '\n'){
printf("present");
} else {
printf("x");
}
with:
if( strchr( buf, '\n' ) )
{
puts( "present" );
}
else
{
puts( "x" );
}
How would you be able to count word lengths and output their occurrences from a string using gets() or fgets()? For example, here is code doing so but using getchar()below. I think writing it in gets() would make it easier to incorporate all of the delimiters in the program rather than having to manually set if statements for each one of those would it not?
#include <string.h>
#include <ctype.h>
const char delim[] = ", . - !*()&^%$##<> ? []{}\\ / \"";
#define SIZE 100
int main(void){
int length[SIZE] = { 0 };
int name[SIZE];
int i = 0, ch, word_len = 0;
int count = 0;
printf("enter sentence: ");
while (1){
ch = getchar();
if (isalpha(ch)){
++word_len;
}
else if (ch == ' ' || ch == '.'){
if (word_len)
length[word_len - 1]++;//-1: to 0 origin
if (ch == '.')
break;
word_len = 0;
}
}
printf("Word Length \tCount \n");
for (i = 0; i<sizeof(length) / sizeof(*length); ++i){
if (length[i])
printf(" %d \t\t%d\n", i + 1, length[i]);
}
return 0;
}
You can build your custom delimiter detection function.
// globals
const char *delim = " .,;:!?\n\0";
const int n_delim = 9;
int is_delim(int c)
{
register int i;
for (i = 0; i < n_delim; i++)
if (c == delim[i]) return 1;
return 0;
}
This function will return 1 every time it can match c with delim. So you can use it like this:
fgets(buffer, 200, stdin);
for (i = 0; i < strlen(buffer); i++) {
if (is_delim(buffer[i])) {
wl[words++] = length;
length = 0;
continue;
}
length++;
}
I'm assuming you're familiar with the fgets function.
You basically will loop through your buffer, making comparisons with each character. Every loop iteration you check if the current character is a word delimiter, if it is, you save the current length and set length=0 for a new word, and at every iteration you increment the length.
You'll need to come up with a way of either not inserting the zero length values due to double delimiters or just ignore them when you're printing the results.
Basically you want to split a string into words, based on some delimiters, and compute their length. The C standard library provides the strtok function, which does exactly what you need: it splits the given string into multiple tokens.
I created a program that asks the user for a word and then it arranges the letters in that word in alphabetical order and stores it in another string.
#include <stdio.h>
main()
{
char in[100],out[100],ch;
int i,len,j=0;
//ask user for a word
printf("Enter a word: ");
scanf("%s",in);
//arrange that word in alphabetical order
for(ch = 'a'; ch <= 'z'; ++ch)
for(i = 0; i < strlen(in); ++i)
if(in[i] == ch)
{
out[j] = ch;
++j;
}
//print the word
printf("%s",out);
fflush(stdin);
getchar();
}
The problem is when word is stored in the other string, there are some extra letters or symbols after that word. Can someone please tell me what could be possibly wrong with my code?
You're not null terminating the output string. printf("%s",out); will keep outputting characters until it finds 0 ('\0'). There are many options to fix this:
terminate the output to the current iterator position after the for-loop:
out[j] = '\0';
make the output the same length as the input:
out[strlen(in)] = '\0';
declare a 0-initialized array:
char out[100] = { 0 };
fill the output array with zero's yourself:
memset(out, 0; sizeof(out));
...
As the sorting is concerned, if it's just for learning then it's fine, otherwise you should pick a more efficient sorting algorithm
C strings are null terminated
Use
out[j] ='\0';
before printf
The %s specifier searches for a null termination.
In your case it keeps on printing until it finds one, so you get some random symbols.
Also avoid use of fflush.
You might want to update your logic to sort uppercase characters too.
You might want to use a sort say bubble sort
l=strlen(in);
for(i = 0; i < l; i++)
{
for(j = i + 1; j < l - 1; j++)
if(in[j-1] > in[j]){
ch = in[j];
in[j] = in[j-1];
in[j-1] = ch;
}
}
printf("Sorted String :%s",in);