-4

When I run this code, I get a segmentation fault. I'm sure I'm doing the pointers wrong, but I'm not sure why or how to fix it. I also included the question I'm trying to answer in picture form. question

#include <stdio.h>
#include <stdlib.h> 

char * repeat_characters(char *s, int n) {
    printf("%s", *s);

    char temp;
    int length = 0;
    int i = 0;
    int j = 0;
    int k = 0;
    char * newString;

    while(s[length]) {
        length++;
        printf("%d", length);
    } // finds length of string

    newString = (char*) malloc(length*n*sizeof(char));

    while(i++ < i*n) {
        temp = s[i];
        while (j++ < n) {
            newString[k] = temp;
            printf("%c", temp);
            k++;
        }
    }
    printf("%s", newString); 
    return newString;
}

int main () {
    char * string[100];
    int numReps = 0;

    printf("Enter a string: ");
    scanf("%s", string);

    printf("\nEnter number of repetitions: ");
    scanf("%d", &numReps);

    repeat_characters(*string, numReps);
    return 0; 
}
  • What @M.M said, plus please use tab, I can barely tell what is in side that one function and what is not, not easy to read. Having said that, please look up how to use malloc. http://www.tutorialspoint.com/c_standard_library/c_function_malloc.htm – Caperneoignis Apr 07 '16 at 22:17
  • Wow. That was rude. The code shows correctly in my text editor. I'm sorry it formats wrong on here. I already tried to look up how to use malloc, and obviously I don't get it, otherwise I wouldn't have posted here. Thanks for the help... – Naomi Sheehan Apr 07 '16 at 22:18
  • `while(i++ < i*n)` => `while (i++ < length)` and reset `j` to 0 before each `while (j++ < n)` – Unimportant Apr 07 '16 at 22:19
  • When I put the # sign, it caused include to be bolded, instead of showing up normally. Is there a formatting code I need to include to make my code show up the way it looks in a text editor? – Naomi Sheehan Apr 07 '16 at 22:20
  • It would show up bolded if you didn't put 4 spaces before it... but you actually did put 4 spaces – M.M Apr 07 '16 at 22:22
  • malloc(length*n*sizeof(char)); sizeof(char) is going to return the size of char, which I dont think you actually want. length * n +1 should be enough, with and extra spot for a null character. – Caperneoignis Apr 07 '16 at 22:23
  • @user1320881, thanks for the help. You were right about those changes, but it's still giving me a segmentation fault. – Naomi Sheehan Apr 07 '16 at 22:28
  • As per @Caperneoignis comment - malloc an extra byte for the string terminator 0 and terminate the string before you printf it. – Unimportant Apr 07 '16 at 22:32
  • Cool, thanks @M.M. Just to be sure, I needed 4 spaces before each line of code to make it format as code? – Naomi Sheehan Apr 07 '16 at 22:33
  • 1
    Naomi, please read about [MarkDown](http://stackoverflow.com/editing-help). And @MattClark... if you're going to [edit posts to fix the formatting](http://stackoverflow.com/revisions/36488107/2), then don't just indent it by 4 and leave it double-spaced and leave in comments in the text like "the `#` and `<` won't show up" with the characters still missing. :-/ – HostileFork says dont trust SE Apr 07 '16 at 22:34
  • What compiler are you using? Have you tried making a break point, and seeing exactly where the program is when you get the SEG Fault? – Caperneoignis Apr 07 '16 at 22:43
  • Your compiler should warn about `printf("%s", *s)` and `scanf("%s", string);`. (If not then try to figure out how to turn up the warning level on your compiler). – M.M Apr 07 '16 at 23:11
  • while(i++ < i*n) {'temp = s[i];' ....................check indices with your debugger and use temp vars instead of expressions in cotrol statements to simplify debugging. NO, it's not rude at insist upon readable source in posts - it's not SO's responsibility to sanitise your code, and your are LUCKY if someeone bothers to ask for you to fix it. Many contributors would just ignore your badly-formatted post and move on to the next question:( – Martin James Apr 07 '16 at 23:17

1 Answers1

1

One of your jobs as a questioner is to shorten your program to the minimum that demonstrates a problem. For instance, the following would give a segmentation fault:

#include <stdio.h>

char * repeat_characters(char *s, int n) {
    printf("%s", *s);
    return NULL;
}

int main () {
    char * string[100];
    scanf("%s", string);

    repeat_characters(*string, 0);
    return 0; 
}

Lots of kinds of problems could be pointed out by compiler warnings. So turn those warnings on. If you're using gcc, then try something like gcc -Wall -Wextra -Werror main.c (or look in your compiler's documentation.)

(The -Werror will turn the warnings into errors, and keep you from accidentally ignoring a warning, which I'd say is a good habit for both learners and experts alike.)

   printf("%s", *s);

format '%s' expects argument of type 'char*', but argument 2 has type 'int'

Here you have a parameter char *s. Depending on context could either be a pointer to a single character, or a pointer to the first character of a multiple-character sequence.

C strings operate on the convention that it's a multiple character sequence, and that the range of characters is eventually terminated by a '\0' (or 0-valued character). So when you call printf you must be sure that the character pointer you pass in is to such a validly formed sequence.

You are passing in *s, which dereferences the pointer-to-a-character to make it into a single character. If you want to print a single character, then you'd need to use %c, e.g. printf("%c", *s);. But you want to print a C string, so you should drop the dereferencing * and just say printf("%s\n", s). (You will likely want \n to output a newline, because otherwise your prints will all run together.)

(Note: The reason C without warnings didn't complain when you passed a character where a character pointer was expected is due to the "weirdness" of functions like printf and scanf. They don't have a fixed number or type of arguments that they take, so there is less checking...warnings help pick up the slack.)

   scanf("%s", string);

format '%s' expects argument of type 'char*', but argument 2 has type 'char**'

Here you have the problem that you've declared s as char * string[100];, which is an array of character pointers, not an array of characters. The duality of a C array being able to behave like a pointer to its first element takes some getting used to, but if you say char string [100]; then string[0] is a char and string can "decay" to a char* synonymous with &string[0]:

Is an array name a pointer?

   while(i++ < i*n)

operation on 'i' may be undefined

The compiler is making a technical complaint here, about modifying the variable i in an expression that also uses i. It's warning about whether the i in i*n would see the value before or after the increment. Avoid this kind of expression...and when-and-if the time comes where you care about what you can and can't do like this, read about sequence points.

But put that aside. What did you intend here? Take the nuance of ++ out of it...what about just while (i < i * n)? When would that be false? Why would it be relevant to solving the problem?

Look through your code and perhaps try commenting it more. What are "the invariants", or the things that you can claim about a variable that would be true on each line? If you were asked to defend why the code worked--with no compiler to run it to see--what would be giving you the certainty that it did the right thing?

Then step through it with a debugger and examples, and check your intuition. If you step over a line and don't get what you expect, then that's when it may be time to start thinking of a question to ask which draws the focus to that line.

There's other issues raised in the comments (for instance, that your malloc() doesn't include space for the terminator, and even once you add in 1 for that space you still have to write a '\0' into it...). Generally speaking your program should perform as many free()s as it does malloc()s. Etc. But hopefully this points you in the right direction for the assignment.

Community
  • 1
  • 1
  • Very nicely worded @HostileFork, and I thought "char * string[100]" read, array of char pointers, but I couldn't remember if that was the way you had to do char arrays in c. Should of went with my gut that the way you do char arrays in C++ would be the same as C. But I now have a better understanding of how to ask a question myself in the future if I am having an issue with compiling it. – Caperneoignis Apr 08 '16 at 13:32