I'm trying to write a program where the morse code of the given text by the system is required. About the converting text to morse code, I wrote them all in main (separately from the program file itself). And now, my aim is to write it as a function in order to use it in the other functions of the program. Whenever I try, it gives a segmentation fault. Can anyone help me to construct the function itself from scratch?
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdint.h>
#include<ctype.h>
#include <time.h>
char * fileName1 = NULL;
char * fileName2 = NULL;
int main(int argc, char * argv[]) {
int n;
for (n = 0; n < argc; n++) {
// printf("Argument %s\n",argv[n]); // prints options delete this in the end,just for debugging
if (strcmp(argv[n], "-text") == 0) {
//text to morsecode
int c, v = 0;
char * str = (char * ) malloc(v);
str = (char * ) realloc(str, (c + strlen(argv[n + 1])));
strcat(str, argv[n + 1]);
strcat(str, " ");
char *alphamorse[]={".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
char *nummorse[]={"-----",".----","..---","...--","....-",".....","-....","--...","---..","----."};
int i;
char str1[1000];
i = 0;
while (str[i] != '\0') {
if (str[i] != ' ' && (!isdigit(str[i]))) {
printf("%s ", alphamorse[toupper(str[i]) - 65]);
}
if (str[i] == ' ') {
printf(" ");
}
if (isdigit(str[i]) && str[i] != ' ') {
printf("%s ", nummorse[str[i] - 48]);
}
i++;
}
printf("\n");
// end of text to morsecode
}
if (strcmp(argv[n], "-o") == 0) {
//output = concat(output, argv[n + 1]);
n++;
continue;
}
if (strcmp(argv[n], "--") == 0) {
if (n + 1 <= argc) {
fileName1 = argv[++n];
printf(" fileName1=%s\n", fileName1);
}
if (n + 1 <= argc) {
fileName2 = argv[++n];
printf(" fileName2=%s\n", fileName2);
}
}
}
return 0;
}
You really don't need or want to be copying the parameters. It seems easiest to just do something like:
#include <stdio.h>
#include <ctype.h>
char *alphamorse[] = {
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", /* A - J */
"-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", /* K - T */
"..-", "...-", ".--", "-..-", "-.--", "--.." /* W - Z */
};
char *nummorse[]={
"-----", ".----", "..---", "...--", "....-",
".....", "-....", "--...", "---..", "----."
};
void
text_to_morse(char c, FILE *out)
{
if( islower(c) ) {
fputs(alphamorse[c - 'a'], out);
fputc(' ', out);
} else if( isdigit(c) ) {
fputs(nummorse[c - '0'], out);
fputc(' ', out);
} else if( isspace(c) ) {
fputc(c, out);
} else {
fputc(' ', out);
}
}
int
main(void)
{
int c;
while( ( c = tolower(getchar())) != EOF ) {
text_to_morse(c, stdout);
}
return 0;
}
Don't even bother with code for manipulating the output file. The shell exists for a reason, and there's no need to reimplement the wheel.
I don't know if this is the bug that's causing an issue, but it is a bug:
int c, v = 0;
char *str = (char *)malloc(v);
str = (char *)realloc(str, (c + strlen(argv[n+1])));
First, c is uninitialized. It could be any value, including a negative value. Hence, undefined behavior in your program.
Also, that malloc followed by a a realloc call isn't needed. Just allocate once and be done with it.
I think this is what you intended to do
size_t len = strlen(argv[n+1]);
str = (char*)malloc(len + 1 + 1); // +1 for space char to be appended, +1 again for null char
strcpy(str, argv[n+1]); // copy string
strcat(str, " "); // append a space
But there's an even simpler solution. You don't even need to copy argv[n+1] into str. Just declare str as a pointer and reference argv[n+1] directly.
const char* str = argv[n+1];
Now str and argv[n+1] reference the same string. And str is valid for the entirety of the program. The rest of your program remains the same.
This looks suspicious:
i = 0;
while (str[i] != '\0') {
if (str[i] != ' ' && (!isdigit(str[i]))) {
printf("%s ", alphamorse[toupper(str[i]) - 65]);
}
if (str[i] == ' ') {
printf(" ");
}
if (isdigit(str[i]) && str[i] != ' ') {
printf("%s ", nummorse[str[i] - 48]);
}
i++;
}
You are redundantly calling isdigit and evaluating to make sure str[i] is not a space. No point in checking if its a space if you already know it's a digit. Either it's a digit, a letter, or something that can't be converted. Your code will errneously treat puncutation marks as values to lookup in alphamorse. The following will skip over punctuation marks and just treat those characters as spaces.
i = 0;
while (str[i] != '\0') {
if ((str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= 'a' && str[i] <= 'z')) {
printf("%s ", alphamorse[toupper(str[i]) - 'A']);
}
else if (isdigit(str[i])) {
printf("%s ", nummorse[str[i] - '0']);
}
else {
printf(" ");
}
i++;
}
Everything after that, I don't know what it's for. General advice is that you parse the arguments from argv[] first. Then do the text conversion outside of the loop that iterates over the command line arguments. Then do your save to file code.
Related
I cant get the right output and I wonder where my mistake is. Probably there are mistakes in loops in the counting reverse. The main problem in my whole code is that it only outputs marks but not words. Also the program must end automatically when putting these three punctuation and shows the output.
This is the expected behavior:
Input: my name is jake.//terminates when putting . and automatically shows the output
Output: jake is name my.
Here is the program fragment of my first loop:
#include <stdio.h>
#define N 70
int main(void) {
char array[N] = { 0 };
char *p;
char mark = 0;
int c;
p = array;
scanf("%d", &c);
while ((c = getchar()) != '\n') {
if (p < array + N) {
if (c == '.' || c == '!' || c == '?')
mark = c;
if (c == ' ') {
*p = '\0';
*p++;
} else
*p = c;
}
}
*p = '\0';
while (--p > array) {
if (p[1])
printf("%s", p + 1);
}
printf("%s", array);
if (mark)
printf("%c", mark);
}
Your code with little modifications:
#include <stdio.h>
#define N 70
int main (void) {
char array[N+1] = { 0 };
char* p;
char mark = 0;
int c;
p = array;
//scanf ("%d", &c); //serves no purpose : are you reading sentence length here?
while ( (c = getchar()) != '\n') {
if (p < array + N) {
if (c == '.' || c == '!' || c == '?') {
mark = c;
*p++ = '\0';
break; // stop reading input
} else if (c == ' ') {
*p++ = '\0';
} else
*p++ = c;
}
}
*p = '\0';
while (--p > array) {
if ('\0' == *p && '\0' != *(p + 1))
printf ("%s ", p + 1);
}
printf ("%s", array);
if (mark)
printf ("%c", mark);
return 0;
}
There is a better way, but that will make use of string library functions.
Here is an alternative where the original string is not modified:
#include <stdio.h>
#include <string.h>
void print_swap(const char *s) {
int p1, p2, tail = strcspn(s, ".!?\n");
for (p1 = p2 = tail; p1 > 0; p1--) {
if (s[p1 - 1] == ' ') {
printf("%.*s ", p2 - p1, s + p1);
p2 = p1 - 1;
}
}
printf("%.*s%s", p2, s, s + tail);
}
int main() {
char array[80];
if (fgets(array, sizeof array, stdin))
print_swap(array);
return 0;
}
I am working on a program that decodes a message provided as a morse code as a command line argument. If the provided string contains 7 spaces it means that I need to print a space to the decoded string. Currently, my program shows all correct letters, but I cannot overcome the issue with locating 7 spaces in a string and printing one space instead.
Here is the issue and how I pass the encoded string:
e3r2p2% ./morse "..- -.. .-. .. .-- --. ..- ....."
udriwg zsh: segmentation fault ./morse "..- -.. .-. .. .-- --. ..- ....."
Program works fine and prints all the decrypted letters (udriwg) till it meets the first (or maybe second) space out of 7;
Here is the code of my program:
int find_morse(const char *s);
bool count_spaces(char *s);
bool is_valid_char(char *s);
bool is_valid_params(int argc, char *argv[]);
void mx_printchar(char c);
void mx_printerr(const char *s);
int mx_strcmp(const char *first, const char *second);
char* mx_strcpy(char* dest, const char* source);
int mx_strlen(const char *s)
int main(int argc, char *argv[]){
if (!is_valid_params(argc, argv)){
mx_printerr("usage: ./morse \"str\"\n");
exit(1);
}
char *output[27]= {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",
"p","q","r","s","t","u","v","w","x","y","z","."};
char *copy;
copy = malloc(mx_strlen(argv[1]) + 1);
if (copy != NULL) {
mx_strcpy(copy, argv[1]);
} else {
mx_printerr("usage: ./morse \"str\"\n");
exit(1);
}
int buff = 0;
char temp[5];
int index;
int space = 0;
int j;
for (int i = 0, n = mx_strlen(copy); i < n; i++) {
if (copy[i] == '.' && copy[i + 1] == '.' && copy[i + 2] == '.'
&& copy[i + 3] == '.' && copy[i + 4] == '.') {
mx_printchar(*output[26]);
}
if (copy[i] != ' ') {
temp[buff] = copy[i];
buff++;
}
if (copy[i] == ' ') {
index = find_morse(temp);
//print letter converted from morse to ENG
mx_printchar(*output[index]);
j = i;
while (copy[j] == ' ') {
space++;
j++;
if (space == 7) {
mx_printchar(' ');
space = 0;
break;
}
}
temp[buff] = '\0';
buff = 0;
for(int j = 0; j <4; j++) {
temp[j] ='\0';
}
}
}
mx_printchar('\n');
free(copy);
return 0;
}
int find_morse(const char *s) {
char *input[27]={".-","-...","-.-.","-..",".","..-.","--.", "....", "..",
".---","-.-",".-..","--","-.", "---",".--.","--.-",".-.",
"...","-","..-", "...-",".--","-..-","-.--","--..","....."};
for (int i = 0; i < 27; i++) {
if (mx_strcmp(s, input[i]) == 0) {
return i;
}
}
return -1;
}
bool count_spaces(char *s) {
int space = 0;
for (int i = 0; s[i] != '\0'; i++) {
if (s[i] == ' ') {
space++;
if (s[i + 1] != ' ') {
if (space != 1 && space != 7) {
return false;
} else {
space = 0;
}
}
}
}
return true;
}
bool is_valid_char(char *s){
int i = 0;
while (s[i] != '\0'){
if (s[i] != ' ' && s[i] != '-' && s[i] != '.') {
return false;
}
i++;
}
return true;
}
bool is_valid_params(int argc, char *argv[]){
if (argc != 2) {
return false;
}
if (!is_valid_char(argv[1])){
return false;
}
if (!count_spaces(argv[1])){
return false;
}
return true;
}
void mx_printchar(char c){
write(1, &c, 1);
}
void mx_printerr(const char *s){
write(2, s, mx_strlen(s));
}
int mx_strcmp(const char *first, const char *second) {
while (*first) {
if (*first != *second) break;
first++;
second++;
}
return *(const unsigned char*)first - *(const unsigned char*)second;
}
char* mx_strcpy(char* dest, const char* source){
if (dest == NULL) {
return NULL;
}
char *ptr = dest;
while (*source != '\0') {
*dest = *source;
dest++;
source++;
}
*dest = '\0';
return ptr;
}
int mx_strlen(const char *s){
int length = 0;
while (s[length] != '\0'){
length++;
}
return length;
}
I believe the issue starts here:
j = i;
while (copy[j] == ' ') {
space++;
j++;
if (space == 7) {
mx_printchar(' ');
space = 0;
break;
}
}
Program prints the decripted letter, then tries to check those spaces but somethis go wrong.
I'd appreciate any suggestions as how to resolve it
When using a program from command line you always put a space as a delimiter between your program name and the parameters and other parameters. So, in your case if there are 7 spaces then a extra space will be added as delimiter between your program name and 7 spaces making it to 8 spaces like this ./morse. So, I'd rather suggest to use any other symbol like ! or any other symbol.
Now for the Segmentation fault error I think that's not happening because of that space counter section that's happening because of this line copy = malloc(mx_strlen(argv[1]) + 1); as you must know that malloc() returns a void * to the allocated space.Now here I don't know what those mx_ functions are. Also some questions popped out in my mind while I was debugging your code those answers are included in the modified code(at somewhat satisfying level) i'm putting below. Please answer them in comments.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Questions
** 1. What are these mx_ functions?
** 2. What is is_valid_params?
** 3. Can't we define *output[27] as *output = "abcdef...z." ?
** 4. In " for(j = 0; j < 4; j++) temp[j] ='\0'; " why j < 4 instead of j < 5?
*/
// Function Prototype
int find_morse(const char *s);
//main()
int main(int argc, char *argv[])
{
char *output[27]= {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","."};
char *copy, temp[5];
int buff = 0, index, space = 0, i, j, n;
// Checking for valid parameters.
if (argc != 2)
{
printf("usage: ./morse \"Invalid Parameters.\"\n");//mx_printerr("usage: ./morse \"str\"\n");
exit(1);
}
copy = (char *)malloc(strlen(argv[1]) + 1);
if (copy != NULL)
strcpy(copy, argv[1]);
else
{
printf("usage: ./morse \"Memory Unavailable.\"\n");
exit(2);
}
for (i = 0, n = strlen(copy); i < n; i++)
{
if (copy[i] == '.' && copy[i + 1] == '.' && copy[i + 2] == '.' && copy[i + 3] == '.' && copy[i + 4] == '.')
putchar(*output[26]);
if (copy[i] != ' ')
temp[buff++] = copy[i];
else
{
j = i;
while (copy[j] == ' ')
{
space++;
j++;
if (space == 7)
{
putchar(' ');
space = 0;
break;
}
}
temp[buff] = '\0';
buff = 0;
// Emptying temp[5]
//for(j = 0; j < 5; j++)
temp[0] = '\0'; // Rest elements will automatically be assigned to \0 by compiler.
}
if(index = find_morse(temp) != -1)
putchar(*output[index]); //print letter converted from morse to ENG
}
putchar('\n');
free(copy);
return 0;
}
int find_morse(const char *s)
{
char *input[27] = {".-","-...","-.-.","-..",".","..-.","--.", "....", "..",".---","-.-",".-..","--","-.", "---",".--.","--.-",".-.","...","-","..-", "...-",".--","-..-","-.--","--..","....."};
for (int i = 0; i < 27; i++)
{
if (strcmp(s, input[i]) == 0)
return i;
}
return -1;
}
Here in this program I didn't understand that how the user will enter morse code one by one or as a string. Because, when matching those morse code entries, I'm sure a logical error would occur.
I have a problem with this code which is supposed to make a reverse sentence.
Example:
Input
Hi my name is Robert
Output
Robert is name my Hi
#include <stdio.h>
#define LEN 50
int main(void)
{
char input, terminator = 0, sentence[LEN+1] = {0};
int i, j, last_space = LEN + 1, posc=0;;
int pos[]={0};
printf("\nEnter a sentence: ");
for (i = 0; (input = getchar()) != '\n'; i++)
{
if(input== ' '){
pos[posc]=i;
posc++;
}
if (input == '.' || input == '?' || input == '!')
{
last_space = i;
terminator = input;
break;
}
sentence[i] = input;
}
if (terminator == 0)
{
printf("Sentence needs a terminating character. (./?/!)\n\n");
return 0;
}
printf("Reversal of sentence: ");
for (i = last_space; i > 0; i--)
{
if (sentence[i] == ' ')
{
for (j = i + 1; j != last_space; j++)
{
putchar(sentence[j]);
}
last_space = i;
putchar(sentence[i]);
}
}
while (sentence[i] != '\0' && sentence[i] != ' ')
{
putchar(sentence[i++]);
}
printf("%c\n\n", terminator);
for(int i=sizeof(pos)-1; i>0; i--){
printf("%.*s", sentence[pos[i-1]], sentence[pos[i]]);
}
printf("%c\n\n", terminator);
return 1;
}
This keeps crashing because of the method at the bottom here:
printf("%c\n\n", terminator);
for(int i=sizeof(pos)-1; i>0; i--){
printf("%.*s", sentence[pos[i-1]], sentence[pos[i]]);
}
printf("%c\n\n", terminator);
return 1;
}
Can someone help me fix this snippet of code for me so that both methods work when run? Thanks.
The array of size 1 is created by the line:
int pos[]={0};
And later you are accessing over the array's limit here:
if(input== ' '){
pos[posc]=i;
posc++;
}
The behaviour is undefined after that. The same mistake presents in the code you've mentioned due to sizeof returns the size in bytes, not just amount of elements.
There is a simplest way to do it,
you just have to write a function who will write the last word of the sentence first, then the second and goes on ..
There you can find a working code
#include <unistd.h>
//This function print the last word or a space
static int print_last(const char *str, int len)
{
int i = 0;
while (len > 0 && str[len] == ' ')
len--;
while (i <= len && str[len - i] != ' ')
i++;
write(1, str + len - i + 1, i);
while (len > 0 && str[len] == ' ')
len--;
if (i < len)
write(1, " ", 1);
return (len - i);
}
int main(int ac, char **av)
{
int len = 0;
if (ac == 2)
{
while (av[1][len])
len++;
len--;
while (len > 0)
len = print_last(av[1], len);
}
write(1, "\n", 1);
return (0);
}
and there, once compiled (to compile --> clang yourFileName.c) , you can call the program like so
./youCompiledProgram 'the sentance you want to be inverted'
I'm trying to split a sentence the user inputs to an array of words so I can later manipulate the words separately as strings.
The code is compiling but prints only garbage after the user input.
I tried debugging but don't see the problem. Can someone help me fix it?
#include <stdio.h>
#include <string.h>
int main() {
char str[1000];
int i = 0;
char rev[1000][1000];
int r = 0;
puts("Enter text:");
gets(str);
int k, length = 0;
printf_s("So the words are:\n");
while (str[i] != '\0') {
if (str[i] == ' ') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != ' ');
printf(" ");
length = (-1);
r++;
} else
if (str[i + 1] == '\0') {
k = i - length;
do {
rev[r][k] = (str[k]);
k++;
} while (str[k] != '\0');
length = 0;
r++;
}
length++;
i++;
}
for (int r = 0; r < 1000; r++)
printf("%s ", rev[r]);
return 0;
}
fix like this
#include <stdio.h>
int main(void) {
char str[1000];
char rev[1000][1000];
puts("Enter text:");
fgets(str, sizeof str, stdin);//Use fgets instead of gets. It has already been abolished.
int r = 0;
int k = 0;
for(int i = 0; str[i] != '\0'; ++i){
if (str[i] == ' ' || str[i] == '\n'){//is delimiter
if(k != 0){
rev[r++][k] = '\0';//add null-terminator and increment rows
k = 0;//reset store position
}
} else {
rev[r][k++] = str[i];
}
}
if(k != 0)//Lastly there was no delimiter
rev[r++][k] = '\0';
puts("So the words are:");
for (int i = 0; i < r; i++){
printf("%s", rev[i]);
if(i < r - 2)
printf(", ");
else if(i == r - 2)
printf(" and ");
}
return 0;
}
Replace you declaration
char rev[1000][1000];
with
char * rev[1000]; // We will need pointers only
int i = 0; // Index to previous array
and all your code after
puts( "Enter text:" );
with this:
fgets( str, 998, stdin ); // Safe way; don't use gets(str)
const char delim[] = ",; "; // Possible delimiters - comma, semicolon, space
char *word;
/* Get the first word */
word = strtok( str, delim );
rev[i++] = word;
/* Get the next words */
while( word != NULL )
{
word = strtok( NULL, delim );
rev[i++] = word;
}
/* Testing */
for (int r = 0; r < i - 1; r++)
printf( "%s\n", rev[r] );
return 0
}
As you can see, all dirty work is done with the strtok() function ("string to tokens") which walks through other and other words ("tokens"), recognizing them as delimited by one or more characters from the string delim.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int count_spaces(char *str)
{
if (str == NULL || strlen(str) <= 0)
return (0);
int i = 0, count = 0;
while (str[i])
{
if (str[i] == ' ')
count++;
i++;
}
return (count);
}
int count_char_from_pos(char *str, int pos)
{
if (str == NULL || strlen(str) <= 0)
return 0;
int i = pos, count = 0;
while (str[i] && str[i] != ' ')
{
count++;
i++;
}
return count;
}
char **get_words(char *str)
{
if (str == NULL || strlen(str) <= 0)
{
printf("Bad string inputed");
return NULL;
}
int i = 0, j = 0, k = 0;
char **dest;
if ((dest = malloc(sizeof(char*) * (count_spaces(str) + 1))) == NULL
|| (dest[0] = malloc(sizeof(char) * (count_char_from_pos(str, 0) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
while (str[i])
{
if (str[i] == ' ') {
dest[j++][k] = '\0';
if ((dest[j] = malloc(sizeof(char) * (count_char_from_pos(str, i) + 1))) == NULL)
{
printf("Malloc failed\n");
return NULL;
}
k = 0;
}
else {
dest[j][k++] = str[i];
}
i++;
}
dest[j][k] = 0;
dest[j + 1] = NULL;
return dest;
}
int main(void) {
char *line = NULL;
size_t n = 0;
getline(&line, &n, stdin);
printf("%s\n", line);
line[strlen(line) - 1] = 0;
printf("%s\n", line);
char **tab = get_words(line);
int i = 0;
while (tab[i])
{
printf("%s\n", tab[i++]);
}
}
here is a long but fully working example
get the user input
then send it to get_words function. It will get the number of words, the number of characters for each words, allocate everything in memory and writes chars then return it. You get a char ** and prints it just tested it it works
If you wish to split a string into an array of strings, you should consider the strtok function from #include <string.h>. The strtok function will the split the string on the given delimiter(s). For your case, it would the " ".
Using the strtok example from Tutorials Point:
#include <string.h>
#include <stdio.h>
int main(){
char str[80] = "This is - www.tutorialspoint.com - website";//The string you wish to split
const char s[] = "-";//The thing you want it to split from. But there is no need to this.
char *token;//Storing the string
/* get the first token */
token = strtok(str, s);//Split str one time using the delimiter s
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );//Print the string
token = strtok(NULL, s);//Split the string again using the delimiter
}
return(0);
}
I have this string: print "Foo cakes are yum"
I need to somehow strip all extra whitespace but leave text between quotes alone. This is what i have so far:
char* clean_strip(char* string)
{
int d = 0, c = 0;
char* newstr;
while(string[c] != '\0'){
if(string[c] == ' '){
int temp = c + 1;
if(string[temp] != '\0'){
while(string[temp] == ' ' && string[temp] != '\0'){
if(string[temp] == ' '){
c++;
}
temp++;
}
}
}
newstr[d] = string[c];
c++;
d++;
}
return newstr;
}
This returns this string: print "Foo cakes are yum"
I need to be able to skip text between thw quotes so i get this: print "Foo cakes are yum".
Here is the same question but for php, i need a c answer: Remove spaces in string, excluding these in specified between specified characters
Please help.
Try this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* clean_strip(char* string)
{
int d = 0, c = 0;
char* newstr = malloc(strlen(string)+1);
int quoted = 0;
while(string[c] != '\0'){
if (string[c] == '"') quoted = !quoted;
if(!quoted && string[c] == ' '){
int temp = c + 1;
if(string[temp] != '\0'){
while(string[temp] == ' ' && string[temp] != '\0'){
if(string[temp] == ' '){
c++;
}
temp++;
}
}
}
newstr[d] = string[c];
c++;
d++;
}
newstr[d] = 0;
return newstr;
}
int main(int argc, char *argv[])
{
char *input = "print \"Foo cakes are yum\"";
char *output = clean_strip(input);
printf(output);
free(output);
return 0;
}
This will produce the output:
print "Foo cakes are yum"
It works by looking for the " character. If it's found it toggles the variable quoted. If quoted is true, then the whitespace removal is skipped.
Also, your original function never allocates memory for newstr. I added the newstr = malloc(...) part. It is important to allocate memory for strings before writing to them.
I simplified your logic a little.
int main(void)
{
char string[] = "print \"Foo cakes are yum\"";
int i = 0, j = 1, quoted=0;
if (string[0] == '"')
{
quoted=1;
}
for(i=1; i< strlen(string); i++)
{
if (string[i] == '"')
{
quoted = 1-quoted;
}
string[j] = string[i];
if (string[j-1]==' ' && string[j] ==' ' && !quoted)
{
;
}
else
{
j++;
}
}
string[j]='\0';
printf("%s\n",string);
return 0;
}