#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    7
    Rep Power
    0

    How to prefix n-letters in front of a string


    hey guys,

    first of all i want to thank you all very much for the answers in my last "how to"-thread. This was very very kind of you all.

    Now, this is my last problem I have to solve. But, again it is really difficult for me since I just started with computer science meaning programming language C.

    A function, let's say char* pre(char* s, int n); is given. What I need to do is fix n-letters in front of this string s.

    Kinda like this. There is a string ("whatsup"). Then I want to add a word with n letters in front of "whatsup" -> "nnnnnwhatsup" -> "hellowhatsup"

    ...how do i do that?

    I started with something..but it is more like a pseudo-code I'd say :D

    Code:
    #include <stdio.h>
    #include <string.h>
    int pre(char *s, int n)
    { 
    int j=0;
    for(n=0;n<=5;n++)
    { s[j-n]=s[n]; }
    return s;
    }
    
    int main()
    { 
    char s[]="whatsup";
    int n;
    pre(s,n);
    printf("pre: %s", pre(s,n);
    getchar();
    return 0;
    }
    I know the code doesnt make really sense. I just wanted to give you an idea what I am trying to solve.

    I would really appreciate if you can tell me how to do it.

    Thanks again! :)
  2. #2
  3. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,385
    Rep Power
    1871
    Well the first thing you need to think about is where you're going to store "hellowhatsup".

    You either need to reserve some memory yourself (a char array), or use malloc to allocate some memory you can use.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  4. #3
  5. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,158
    Rep Power
    2222
    So much wrong with that code, far beyond the fact that you didn't indent it -- preserving your code's indentation and hence its formatting is why we use code tags, so why defeat the purpose? But you say to ignore the code, so what can we say? But if s is a char pointer, then don't return it as an int. And every time you call pre() you prepend onto s, so don't call it twice. And if you want to prepend a string onto s, then pass in that string; you can get its length with strlen.

    Are you allowed to use library functions such as strcpy and strcat? Do you want to make s arbitrarily large in order to hold whatever the result will become? Or do you want to resize it as you go. For the latter, you would need to malloc and pass in the address of the pointer s in order to change it.
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    7
    Rep Power
    0
    Originally Posted by dwise1_aol
    So much wrong with that code, far beyond the fact that you didn't indent it -- preserving your code's indentation and hence its formatting is why we use code tags, so why defeat the purpose? But you say to ignore the code, so what can we say? But if s is a char pointer, then don't return it as an int. And every time you call pre() you prepend onto s, so don't call it twice. And if you want to prepend a string onto s, then pass in that string; you can get its length with strlen.

    Are you allowed to use library functions such as strcpy and strcat? Do you want to make s arbitrarily large in order to hold whatever the result will become? Or do you want to resize it as you go. For the latter, you would need to malloc and pass in the address of the pointer s in order to change it.
    thank you for you answer. no i am not allowed to use library functions i guess. im only allowed to use strlen. plus, i want to resize my string as i go...well there are many mistakes. as i said i dont really have a plan to programm it.
    any hints for me. or maybe a pseudocode...?

    thank you very much.

    -Anna
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,158
    Rep Power
    2222
    I would have pre() take two char* arguments: the base string and the prefix. The function will prepend the prefix onto the base string and return the pointer by one or both ways.

    The code itself in the function would run something like:
    1. Use strlen on both strings to get their lengths.
    2. malloc a new char* string whose length is the sum of the two strings' lengths, plus one more for the null-terminator -- if you don't know what the null-terminator is, then review C-style strings; it's the '\0' that marks the end of a string.
    3. Copy the prefix string into the new string starting at the new string's beginning. Do not include its null-terminator.
    4. Copy the base string into the new string starting at the next position after the prefix. This time do include its null-terminator.
    5. Free the base string.
    6. Return the new string.

    Now, this requires that the base string that you pass in be a char pointer, not an array; you cannot free or malloc an array name.

    Also, there are two ways to "return" a value from a function. You can use the return statement, or you can pass a pointer to the variable you want to return. Doing the latter would require you to pass base as a pointer to a pointer to char (a char**) and to dereference base as you use it in the function. If you use the former approach, a return statement, then you could return the pointer and assign it to base.

    Returning the pointer would also allow you to use it in another function call, such as you tried in that printf. However, this would cause that pointer to be dropped (ie, you would no longer have access to that malloc'd memory having not saved the pointer) thus creating a memory leak. In that case, you would want to combine both methods, updating the base argument with a char** in the parameter list as well as returning the pointer solely so that it can be used in a function call, which is what strcpy does (only strcpy just changes the contents of the dest string, not its address).

    This is all assuming that you want the new string to replace the old base string. Another scenario would be that you want to create a string and leave the original two alone. The approach would be the same, only you won't try to free base. You could also declare base and prefix to be arrays or even literal strings. The return issues would remain the same, though.

    So, the first thing you need to do is to develop a plan. What specifically do you want to do? That would include the various ways that you'd want to use the function. Then from those requirements write down in English or in pseudocode what you will need to do to meet those requirements. From there, the coding step will be easy.
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    7
    Rep Power
    0
    Thank you very much for all this information.

    I have tried something. It doesn't really work, though.

    Do you know why?

    Code:
    #include <stdio.h>
    #include <string.h>
    
    
    int pre(char *s, int n)
    {
        int j;
        for(j=0;s[j]!='\0';j++)
        {
            s[n]=s[j];
            n++;
        }
        s[n]='\0';
        return *s;
    }
    
    
    int main()
    {
        char s[]="whatsup";
        int n=5;
        printf("pre: %s", pre(s,n));
        getchar();
        return 0;
    }
  12. #7
  13. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,158
    Rep Power
    2222
    First, just exactly what do you mean by "It doesn't really work"? Of course it works! It's doing exactly what you are telling it to do! Programs have no other choice but to do what we tell them to do. The problem is when what you're telling it to do isn't what we want it to do.

    But the real problem with your "It doesn't really work" is that you are telling us absolutely nothing! Look at me! Do I look like a mind-reader? No, seriously, look at me! Look at me right in the eye!

    What do you mean that you cannot see me? Of course you cannot see me. But you expect me to see what your program is doing and you expect me to know exactly what you are expecting your program to do and to be able to tell why instead what you expect you are getting the output/behavior that I cannot see. Just because you can see something and know something doesn't mean that everybody else can also see and know that same thing without having been informed about it. That realization is normally acquired by human children by the age of 5 years, usually before then. I have to assume that you are much older than 5 and that you are not developmentally challenged, so why are you reverting back to that pre-developmental state when you log in here? Well, at least you posted the code; it's amazing how many pre-developmentals here ask us to explain what's wrong with their code but neglect to ever show us that code.

    When you present a problem that you need help on from us, then you must give us information.

    You must tell us the nature of the problem.

    Does it not compile? In that case, you need to tell us what the error and warning messages are. You also need to tell us what language this is (C99 is not the same thing as C) and also what compiler you're using.

    Does it compile without errors but with warnings? You need to correct those warnings too. Warnings are telling you that your code is messed up and that if you were foolish enough to try to run the program it would not do what you expect it to do. Warnings are much more important than errors. Never ignore warnings. Your program as-is gives warnings that you are ignoring.

    Does it compile cleanly (ie, no errors or warnings), but crashes when you run it? You have to tell us that, along with what you did to lead to that crash; ie, did you just run it or did you enter a particular command or data?

    Does it run, but gives you output that isn't what you expect? Then you need to tell us what output you expect and what it's giving you instead. If that output depends on input, then you also need to tell us exactly what that input was.

    And so on. There is all that information that we need from you, none of which is provided by "It doesn't really work". Even less information is provided by your "I have tried something."

    We're here to offer our help. We are not here to play stupid guessing games. We can be a valuable tool. Use us properly; don't abuse us. Using a tool properly makes all the difference between getting the job done and losing a body part.
  14. #8
  15. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,158
    Rep Power
    2222
    When I compile your program with MinGW gcc, I get this output:
    C:\otros\dcw>gcc -Wall pre.c
    pre.c: In function `main':
    pre.c:22: warning: format argument is not a pointer (arg 2)

    C:\otros\dcw>
    This is Line 22:
    printf("pre: %s", pre(s,n));
    Can you see why it's giving you that warning? If not, then look again. Still can't see it? In the format string, what kind of a value are you telling printf to expect? "%s" says that it should expect a string, which is a char* . What are you giving it instead? Yes, you do know the answer to that question. What's the return type of pre()? It's int, isn't it? Is int a char pointer? No, it is not. For that matter, the two types are completely incompatible.

    So what did you do that? What do you expect it to do? What do you expect pre() to return? Based on that, what data type should pre() return?

    Now look at pre():
    Code:
    int pre(char *s, int n)
    {
        int j;
        for(j=0;s[j]!='\0';j++)
        {
            s[n]=s[j];
            n++;
        }
        s[n]='\0';
        return *s;
    }
    Look at that return statement and tell me what you are having it return. You're telling pre() to return the first character in the string, s. That would 'w', whose integer value is 77. Is that what you want it to do? I certainly can't answer that, since it's your program; I don't know what you're trying to do there. Yes, you tried to describe that before, but your function doesn't even begin to try to prepend anything to the string, s.

    pre() makes absolutely no sense, but at least the very minor changes you made has made it slightly less extremely screwed up than it was before. What did I advise you about design? Design the function beforehand. Figure out what it needs to do and work out what steps it has to go through to do that. Until you have a clear vision of the design, trying to throw code in it is worse than a waste of time. What is the design of pre()?

    Now a much more important matter: you are clobbering data in main()!
    char s[]="whatsup";
    That declares s as being eight (8) characters in length, the seven characters of "whatsup" followed by the null-terminator. In pre(), you are going to change "whatsup" into something longer. There's no room in s to accommodate that, so s will overflow. When you overflow a buffer, then you overwrite what's next to it in memory. That's called clobbering and it's not only the source of horrific "unexplainable" problems, data corruption, and program crashes, but also is a prime tool in the arsenal of hackers. But we discussed all that already, though you ignored it.

    Also, with the incrementing of n in pre()'s for-loop, it looks like you will be trapped in an infinite loop as soon as you have overwritten s' null-terminator or until it crashes the program.

    Which returns us to the question of what you could possibly have meant by "It doesn't really work"
  16. #9
  17. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    7
    Rep Power
    0
    Ok. Thank you for the answer.
    I looked some of the things up that you mentioned. I must say that it is really difficult for me. Since I am new to programming. I never did anything cimputer scientific before this. This is my first course. So most of the things u mention are new. This whole char, int, for, while, ... is all new.
    Anyway, I know where you coming from...me just throwing something out there is not enough for you to help me.

    So, I tried to programm your pseudocode from above.

    Code:
    #include <stdio.h>
    #include <string.h>
    
    
    int prefix(char *s1, char *s2)
    {
        int i,j;
        int k=strlen(s1);
        int l=strlen(s2);
        char a[]=char*(malloc(k+l+1));
    
        for(i=0;s2[i]!='\0';i++)
        {
            a[i]=s2[i];
        }
    
        for(j=0;s1[j]!='\0';j++)
        {
            a[l]=s1[j];
            l++;
        }
        a[l]='\0';
    
        return a;
    
    
    int main()
    {
        char s1[]="whatsup";
        char s2[]="yes";
        printf("prefix: %s", prefix(s1,s2));
        getchar();
        return 0;
    }
    Compiler says:
    In function prefix:
    Line 10: syntax error before "char"
    Line 24: [Warning] return makes integer from pointer without cast
    Line 24: [Warning] funtion returns address of local variable
    Line 34: syntax error at the end of input

    I am using wxDev-C++. But, I saved the file as a C source file (*.c). So, I hope this works. It is a very simple program/compiler.

    Now, I can't solve any of these. Where is the syntax error in line 10? What is "cast"? Where is the syntax error at the end of input in line 34? I mean there is no real input. I though input is scanf? Or am I wrong?

    Thank you for your help again.
  18. #10
  19. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,158
    Rep Power
    2222
    Types. C is strongly typed. Data has to be declared to be of a specific data type and has to be treated accordingly. The compiler enforces all that.

    Data is ones and zeros, bits collected into bytes. What do all those ones and zeros mean? Depends. What data means depends on what data type the computer treats it as being. There's nothing intrinsically different between characters, integers of varying size, floating-point values, pointers; bits are bits and bytes and bytes. All that is different is how the program is told to treat those bits and bytes. We use data types to do that.

    You need to work with characters so you use the char type, which you can only do certain things with. Integer arithmetic, counting etc, so you use a type of int, which you can only do certain things with. Decimal fraction? Floating-point types. And pointer types to point to objects of the other types -- pointers are simply memory addresses.

    So then type compatibility is an important issue in C. Sometimes you may need to work around type compatibility issues, which is when you tell the compiler that you want it to treat this variable as a different data type. That is called type casting. That answers your question, "What is "cast"?".

    One compatibility issue is that when you return a value from a function, it has to be of a data type that is compatible with the function's return type. You declare prefix() to return an int, yet you try to return a char pointer. Those two data types are not compatible. You could force the issue with a type cast, but that still would not make any sense here. That's what those Line 24 warnings are about.

    In line 31, you are telling printf to expect a char pointer, but then you give it an int instead, an incompatible data type. I already went over this. I think you need to change prefix to return a char pointer instead of int. It really is that important.

    On Line 10, you just got the syntax all wrong. Try this instead:
    char *a = malloc(k+l+1);

    The syntax error at Line 34 was that it reached the end of the program unexpectedly. You forgot the close brace at the end of the function, prefix.

    PS

    Before you can use a function, the compiler needs to know about it. For the standard library functions, you need to #include the header file that contains their information. In order to use printf, you #include'd stdio.h .

    You need to do the same for malloc(). Read the documentation for malloc; that always tells you what header file to use. When you use a library function, always read its documentation.

    BTW, for malloc() it's malloc.h . But it's also in stdlib.h .
    Last edited by dwise1_aol; April 20th, 2013 at 09:06 PM.
  20. #11
  21. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    7
    Rep Power
    0
    Thank you again. I have changed the things you mentioned. And it works now.

    Thank you.

IMN logo majestic logo threadwatch logo seochat tools logo