0

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);

}
KittMedia
  • 7,368
  • 13
  • 34
  • 38
DeathToxic
  • 157
  • 1
  • 7
  • When the question is "Attach a String to another String in C", why did you tag it with C++? Strings in C and C++ are quite different. – M Oehm Jan 08 '16 at 07:42
  • Why are you implementing yourself the string concatenation? You should use 'strcat' for that – arainone Jan 08 '16 at 07:43
  • 2
    Don't use `gets`. It doesn't even exist in newer standards. Going straight from input to a buffer overrun is that terrible. `fgets` is the better C option. – chris Jan 08 '16 at 07:44
  • 1
    he's not allowed to use other library functions – Serve Laurijssen Jan 08 '16 at 07:44
  • 1
    okay sorry, thought C and C++ are very close to each other And I have to use gets, I have a strict rule from my teacher I have to follow – DeathToxic Jan 08 '16 at 07:47
  • Is only space of behind to be ignored? (E.g `"Hi Hello "` => `"Hi Hello"`) – BLUEPIXY Jan 08 '16 at 07:49
  • 1
    @DeathToxic Your teacher should read http://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used – Andreas Fester Jan 08 '16 at 07:51
  • It must be every space, doesn't matter before or after – DeathToxic Jan 08 '16 at 07:51
  • 1
    When "World" is attached afterwards of "Hello ", it makes "Hello World" in general. DeathToxic's 'attached afterwards' may have some other functions. What is that? 'Remove space at tail?', 'Remove all spaces?'. It is difficult to guess from your question. – Fumu 7 Jan 08 '16 at 07:55
  • He just told me I have to learn some basics first, I am pretty new to this so my knowledge is very limited, but I can use fgets without library too right? What for other arguments does the fgets need? – DeathToxic Jan 08 '16 at 07:56
  • @Fumu7 I tried to somehow block the spaces which the user is typing in, everytime the user types a space or a tab, I try to not allow it, but I didn't know how to do this in the code – DeathToxic Jan 08 '16 at 07:59
  • 1
    Try to convince your teacher that `gets` is obsolete. Show him the relevant paragraph in the latest C standard. That would at least tell him that you read some part of that standard. Also use English looking variable names and comments on this English-speaking forum – Basile Starynkevitch Jan 08 '16 at 08:26
  • Compile with all warnings & debug info (`gcc -Wall -Wextra -g` when using [GCC](http://gcc.gnu.org/)...). Then learn how to **use the debugger** (`gdb`) and read more material about [C](http://en.cppreference.com/w/c) – Basile Starynkevitch Jan 08 '16 at 08:29
  • Consider not using `gets()` at all as its deprecated and error-prone. Try using something like `scanf()` or `fgets()` – Magisch Jan 08 '16 at 09:02
  • "..I can use fgets without library too .." Wrong terminology; you mean "without its *header file*". But no worries, since `fgets` is also in `stdio.h`. "What for other arguments does the fgets need?" That is exactly what a search engine is for. – Jongware Jan 08 '16 at 09:48

5 Answers5

1

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;
}
M Oehm
  • 28,726
  • 3
  • 31
  • 42
1

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.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • You actually forget to answer the actual question: how to ignore spaces between 2 strings before concatenating them (`"Hello "` <- that last one). After decreasing the index to remove the `\n` at the end of the first line, test for some more spaces, and similar for the second string but then at the start. – Jongware Jan 08 '16 at 09:52
  • Note: `int i = 0; while (eingabe1[i]) i++; if (eingabe1[i-1];` is the groundwork for a hacker exploit. User just needs to type or something like that to incur UB. – chux - Reinstate Monica Jan 08 '16 at 17:33
  • Hmm, I guess in that case, given the `int` declaration, limiting `i > 0` would constrain its range between `0 - length` – David C. Rankin Jan 08 '16 at 17:44
0
/**
    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;   
}
milevyo
  • 2,165
  • 1
  • 13
  • 18
0

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);

}
DeathToxic
  • 157
  • 1
  • 7
0

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.

Alan Corey
  • 577
  • 6
  • 10