How to output a string in a marquee fashion? - c

I want to be able to input a string (with spaces) and have it displayed like a moving sign. For example:
Input:
Hello World!
5 (This signifies the number of characters the sign can hold)
Output:
Sign #1:
[Hello]
[ello ]
[llo W]
[lo Wo]
[o Wor]
[ Worl]
[World]
[orld!]
[rld! ]
[ld! H]
[d! He]
[! Hel]
This is what I have so far. If someone could direct me on what to do next I would greatly appreciate it!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int num_of_chars, i;
char sign[30];
char *arrayofsign = malloc(10 * sizeof(char));
scanf("%[^\n]s", sign);
arrayofsign = sign;
printf("%s\n", arrayofsign);
scanf("%d", &num_of_chars);
for (i = 0; i < num_of_chars; i++) {
printf("[]");
}
}

Use carriage return '\r' to move the cursor back to the beginning of a line. Assuming a POSIX system (because of the use of nanosleep()), you could code like this. Note the use of the %*.*s notation to specify how long a sub-section of the string to print.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main(void)
{
char sign[50];
struct timespec d = { .tv_sec = 0, .tv_nsec = 100000000 };
printf("What should I say? ");
if (scanf("%49[^\n]", sign) == 1)
{
printf("Sign: [%s]\n\n", sign);
int t_len = strlen(sign);
for (int i = 0; i < 10; i++)
{
for (int l_len = 0; l_len < t_len; l_len++)
{
int r_len = t_len - l_len;
/* Rotate to right */
//printf("\r[%*.*s%*.*s]", l_len, l_len, sign + r_len, r_len, r_len, sign);
/* Rotate to left */
printf("\r[%*.*s%*.*s]", r_len, r_len, sign + l_len, l_len, l_len, sign);
fflush(stdout);
nanosleep(&d, 0);
}
}
putchar('\n');
}
return 0;
}
The output at the end was:
What should I say? Hello World, and how are you today?
Sign: [Hello World, and how are you today?]
[?Hello World, and how are you today]
It would be better if the code added a string such as " ... " after the entered text so it wraps better. That is trivial to do if you reserve enough space in the string for the padding on input (change 49 into 44 since there are five characters in the padding).
Piping the output through tr '\r' '\n' yields:
Hello World, and how are you today?
What should I say? Sign: [Hello World, and how are you today?]
[Hello World, and how are you today?]
[ello World, and how are you today?H]
[llo World, and how are you today?He]
[lo World, and how are you today?Hel]
[o World, and how are you today?Hell]
[ World, and how are you today?Hello]
[World, and how are you today?Hello ]
[orld, and how are you today?Hello W]
[rld, and how are you today?Hello Wo]
[ld, and how are you today?Hello Wor]
[d, and how are you today?Hello Worl]
[, and how are you today?Hello World]
[ and how are you today?Hello World,]
[and how are you today?Hello World, ]
[nd how are you today?Hello World, a]
[d how are you today?Hello World, an]
[ how are you today?Hello World, and]
[how are you today?Hello World, and ]
…
which shows how the output changes over time. It also illustrates the problems with piping standard output to another command.
An alternative (simpler) version of the printf() statements:
/* Rotate to right */
putchar('\r');
printf("[%.*s%.*s]", l_len, sign + r_len, r_len, sign);
printf(" ");
/* Rotate to left */
printf("[%.*s%.*s]", r_len, sign + l_len, l_len, sign);
That code shows the text scrolling both to the right and to the left at once. In this context, the leading * in the %*.*s conversion specification isn't needed (but there are others where it can be useful and even necessary), so only one length argument is needed for each string.

It's not exactly clear from the question what problem are you having, but I hope that a working source code example will help you anyway.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
//There is no built-in "sleep" in C99, hence this function. You can use any method you want to implement a delay.
void customSleep( int seconds )
{ // Pretty cross-platform, both ALL POSIX compliant systems AND Windows
#ifdef _WIN32
Sleep( 1000 * seconds );
#else
sleep( seconds );
#endif
}
int main(){
char text[30];
int signLength;
printf("Enter text: ");
scanf ("%[^\n]%*c", text); //Reading a line with spaces.
printf("Enter sign length: ");
scanf("%d", &signLength);
printf("SignLength: %d\n", signLength);
printf("Text: %s\n", text);
int currentStartPosition = 0;
setbuf(stdout, NULL); //disable buffering for stdout. Otherwise, if the string is short, it doesn't print immediately.
//Alternatively, you could print a new line character at the end.
while (1) {
for (int i = 0; i < signLength; ++i) {
int indexOfCharacterToPrint = (currentStartPosition + i) % strlen(text);
printf("%c", text[indexOfCharacterToPrint]);
}
++currentStartPosition;
customSleep(1);
//Stole this method from other answers :)
printf("\r");
}
}
Additional links:
Implement time delay in C (SO question).
Why does printf not flush after the call unless a newline is in the format string? (SO question)

Do you mean the following?
#include <stdio.h>
#include <string.h>
int main( void )
{
char s[] = "Hello World!";
size_t n = strlen( s );
size_t m = 5;
for ( size_t i = 0; i < n; i++ )
{
putchar( '[' );
for ( size_t j = 0; j < m; j++ )
{
char c = s[(i + j) % ( n + 1 )];
if ( !c ) c = ' ';
putchar( c );
}
printf( "]\n" );
}
}
The program output is
[Hello]
[ello ]
[llo W]
[lo Wo]
[o Wor]
[ Worl]
[World]
[orld!]
[rld! ]
[ld! H]
[d! He]
[! Hel]
If so then all you need to do is to add inputting of the string and the value of the variable m.

You should repeatedly output the signage display, go back to the beginning of the line with \r, wait a bit and start again with starting point one position to the right in the signage string:
#include <stdio.h>
#include <unistd.h>
int main(void) {
int num_of_chars;
size_t i;
char sign[30];
char arrayofsign[60];
if (scanf("%29[^\n]", sign) != 1 || *sign == '\0') {
printf("invalid input\n");
exit(1);
}
strcpy(arrayofsign, sign);
while (strlen(arrayofsign) < sizeof(arrayofsign) - 1) {
strcat(arrayofsign, " ");
strncat(arrayofsign, sign,
sizeof(arrayofsign) - 1 - strlen(arrayofsign));
}
if (scanf("%d", &num_of_chars) != 1 || num_of_chars <= 0) {
printf("invalid input\n");
exit(1);
}
for (i = 0;; i = (i + 1) % strlen(sign)) {
printf("[%.*s]\r", num_of_chars, arrayofsign + i);
fflush(stdout);
sleep(1);
}
return 0;
}

I suggest creating a duplicate string that contains the original string, twice. In that case the printing becomes really simple.
Obtain the length of the string, allocate a new string with double the length (don't forget to allocate space for the null terminator), then copy the string into the new string twice. The new string will look like this:
char string[] = "Hello world!" ;
...
char new_string[] = "Hello world!Hello world!" ;
Then simply print it from an offset until you reach the length of the original string and reset the index:
size_t i = 0;
while( 1 )
{
printf( "%.5s" , new_string+i );
i++;
if( i == string_length )
{
i = 0;
}
MoveCursor();
Delay();
}
The number 5 in the printf format syntax "%.5s", means that at most 5 characters of new_string will be printed.
Function MoveCurson should reset the printing position in the console to the start of the line. This function has to be implemented by you, you can start here: Update printf value on same line instead of new one
Function Delay must be implemented by you and it should pause the program for a while. Doing this is platform specific so there is not single answer.

The following program prints all substrings only once:
#include <stdio.h>
#include <string.h>
int main(void)
{
int num_of_chars, i;
char sign[30], two_sign[60];
fgets(sign, sizeof sign, stdin);
scanf("%d", &num_of_chars);
sign[strlen(sign) - 1] = '\0'; // discard '\n'
strcpy(two_sign, sign);
strcat(two_sign, sign);
for (i = 0; sign[num_of_chars + i]; i++)
{
printf("[%.*s]\n", num_of_chars, two_sign + i);
}
return 0;
}
The %.*s enables me to specify the max length of the string to be printed by num_of_chars.

This is what I whipped up real quick.
Commented every line of code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h> /* Use this if windows */
/* #include <unistd.h> for unix and change Sleep to sleep */
char * marquee(char * string, int length, int index)
{
/* string = "Hello, World!!" */
/* Display holds five characters and one for the null */
char * display = malloc(sizeof(char) * (length + 1));
/* This pointer will walk down the string for us */
/* For example: "Hello" then "ello " then "llo H", etc. */
char * travel = malloc(sizeof(char) * 256);
/* This pointer is to concatenate the string that moves off the screen back to the end of travel. This is necessary for the marquee effect. */
/* For example: "Hello World!! " then "ello World!! H" then "llo World!! He" */
char * temp = malloc(sizeof(char) * (strlen(string) + 1));
/* We need a counter to walk through the string */
int counter = 0;
/* Travel should start at the beginning of the string */
/* For example: travel = "Hello, World!!" */
strcpy(travel, string);
/* Loop through string */
while (counter < index)
{
/* First letter of travel needs to equal temp */
/* For example: */
/* First pass: travel[0] = 'H' temp[0] = 'H' */
/* Second pass: travel[0] = 'e' temp[1] = 'e' /*
/* Third pass: travel[0] = 'l' temp[2] = 'l' /*
/* etc... */
temp[counter] = travel[0];
/* Walk down the string */
/* For example: travel = "Hello, World!!", then "ello, World!!", then "llo, World!!" etc. */
travel++;
/* Increment counter to loop through string */
counter = counter + 1;
}
/* We need a null at the end */
temp[counter + 1] = '\0';
/* If we don't add a space at the end, we get a "ello, World!!H" on the next line */
strcat(travel, " ");
/* Second pass: "ello, World!! H" Third pass: "llo, World!! He", etc. */
strcat(travel, temp);
/* Display = "Hello", then "ello ", then "llo H", etc. */
strncpy(display, travel, length);
/* Add the null or else */
display[length] = '\0';
return display;
}
/* This function clears the screen to give the marquee effect.
The following is a system call to the operating system to do the clearing. */
void clrscr()
{
system("#cls||clear");
}
int main()
{
/* Our starting string */
char * string = "Hello, World!!";
/* Get length of string, we'll use it later */
int len = strlen(string);
/* My version of C sucks, so I have to declare this outside the loop*/
int i;
/* Infinite Loop, so marquee never dies */
while (1)
{
/* Loop through entire length of string */
for (i = 0; i < len; i++)
{
/* Get five character string from marquee function */
char * temp = marquee(string, 5, i);
/* Print string...which is only 5 characters big */
printf("%s\n", temp);
/* Sleep for one second or else it will move by too fast to see */
Sleep(1000);
/* Clear Screen */
clrscr();
}
}
return 0;
}
Works, but just realized I didn't bother freeing memory. Hah. Too used to javascript.
You might have to comment out windows.h and comment in unistd.h if you're using UNIX. Also, you would need to make Sleep, sleep (notice the lowercase 's') if you're on UNIX.

// I think i should not help you to do your homework.
#include <stdio.h>
#include <string.h>
void marquee(const char* input, unsigned int loopNumber) {
int start = 0;
size_t inputLen = strlen(input);
while (loopNumber--) {
printf("[");
if (start == inputLen) start = 0;
int end = start + 5;
if (end > inputLen) end -= inputLen;
for (int i = start; i != end; i++) {
if (i == inputLen) i = 0;
printf("%c", input[i]);
}
printf("]\n");
start++;
}
}
int main() {
marquee("Hello world! ", 10);
return 0;
}

Related

How to add space between the characters if two consecutive characters are equal in c?

I need to add add space if two consecutive characters are same.
For example:
input:
ttjjjiibbbbhhhhhppuuuu
Output:
t tjjji ibbbbhhhhhp puuuu
If the two consecutive characters are same then need to print space between two consecutive characters....if the consecutive characters are greater than two no need to add space.
My code:
#include <stdio.h>
#include <string.h>
int main()
{
char s[100]="ttjjjiibbbbhhhhhppuuuu";
for(int i=0;i<strlen(s);i++){
if(s[i]!=s[i-1] && s[i]==s[i+1]){
s[i+1]=' ';
}
}
printf("%s",s);
}
my output:
t j ji b b h h hp u u
What mistake i made??
Your primary mistake is writing to your input when the string needs to grow. That's not going to work well and is hard to debug.
This is typical of C Code: measure once, process once. Same-ish code appears twice.
Variables:
int counter;
char *ptr1;
char *ptr2;
char *t;
Step 1: measure
for (ptr1 = s; *ptr1; ptr1++)
{
++counter;
if (ptr1[0] == ptr1[1] && ptr1[0] != ptr1[2] && (ptr1 == s || ptr1[-1] != ptr1[0]))
++counter;
}
Step 2: copy and process
t = malloc(counter + 1);
for (ptr1 = s, ptr2 = t; *ptr1; ptr1++)
{
*ptr2++ = *ptr1;
if (ptr1[0] == ptr1[1] && ptr1[0] != ptr1[2] && (ptr1 == s || ptr1[-1] != ptr1[0]))
*ptr2++ = ' ';
}
ptr2[0] = '\0';
Another solution: Calculate the length of consective characters and handle the special case(Length == 2).
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
char s[100] = "ttjjjiibbbbhhhhhppuuuu";
char tmp_ch = s[0];
int cnt = 1;
for (int i = 1; i < strlen(s); i++) {
while (s[i] == tmp_ch) {
cnt++;
i++;
if (i == strlen(s)) {
break;
}
}
if (cnt == 2) {
putchar(tmp_ch);
putchar(' ');
putchar(tmp_ch);
} else {
for (int j = 0; j < cnt; j++) {
putchar(tmp_ch);
}
}
tmp_ch = s[i];
cnt = 1;
}
return 0;
}
Another approach is to use strspn() to get the number of consecutive characters as you work down the string. The prototype for strspn() is:
size_t strspn(const char *s, const char *accept);
Where strspn() returns the number of bytes in the initial segment of s which consist only of bytes from accept. (e.g. using the current character in a 2-character string as accept, it gives the number of times that character appears in sequence)
Tracking the number of charters returned and updating an offset from the beginning allows you to simply loop letting strspn() do the work as you work though your string. All you are concerned with is when strspn() returns 2 identifying where two, and only two, of the same character are adjacent to one another.
You can do:
#include <stdio.h>
#include <string.h>
int main (void) {
char *input = "ttjjjiibbbbhhhhhppuuuu";
char chstr[2] = {0}; /* 2 char string for accept parameter */
size_t nchr = 0, offset = 0; /* no. chars retured, current offset */
*chstr = input[offset]; /* initialize with 1st char */
/* while not at end, get number of consecutive character(s) */
while (*chstr && (nchr = strspn (input + offset, chstr))) {
if (nchr == 2) { /* if 2 - add space */
putchar (input[offset]);
putchar (' ');
putchar (input[offset]);
}
else { /* otherwise, loop nchr times outputting char */
size_t n = nchr;
while (n--)
putchar(input[offset]);
}
offset += nchr; /* add nchr to offset */
*chstr = input[offset]; /* store next char in string */
}
putchar ('\n'); /* tidy up with newline */
}
Example Use/Output
$ /bin/space_between_2
t tjjji ibbbbhhhhhp puuuu
Let me know if you have further questions concerning the use of strspn().

add additional letters in a string if there are two same letters beside each other

I'm trying to add an additional letter if there are two equal letters beside each other.
That's what I was thinking, but it doesn't put in an x between the two letters; instead of that, it copies one of the double letters, and now I have, for example, MMM instead of MXM.
for (index_X = 0; new_text[index_X] != '\0'; index_X++)
{
if (new_text[index_X] == new_text[index_X - 1])
{
double_falg = 1;
}
text[index_X] = new_text[index_X];
}
if (double_falg == 1)
{
for (counter_X = 0; text[counter_X] != '\0'; counter_X++)
{
transfer_X = counter_X;
if (text[transfer_X - 1] == text[transfer_X])
{
text_X[transfer_X] = 'X';
cnt_double++;
printf("%c\n", text[transfer_X]);
}
text_X[transfer_X] = text[transfer_X - cnt_double];
}
printf("%s\n", text_X);
}
If you're trying to create the modified array in text_X, copying data from new_text and putting an X between adjacent repeated letters (ignoring the possibility that the input contains XX), then you only need:
char new_text[] = "data with appalling repeats";
char text_X[SOME_SIZE];
int out_pos = 0;
for (int i = 0; new_text[i] != '\0'; i++)
{
text_X[out_pos++] = new_text[i];
if (new_text[i] == new_text[i+1])
text_X[out_pos++] = 'X';
}
text_X[out_pos] = '\0';
printf("Input: [%s]\n", new_text);
printf("Output: [%s]\n", text_X);
When wrapped in a basic main() function (and enum { SOME_SIZE = 64 };), that produces:
Input: [data with appalling repeats]
Output: [data with apXpalXling repeats]
To deal with repeated X's in the input, you could use:
text_X[out_pos++] = (new_text[i] == 'X') ? 'Q' : 'X';
It seems that your approach is more complicated than needed - too many loops and too many arrays involved. A single loop and two arrays should do.
The code below iterates the original string with idx to track position and uses the variable char_added to count how many extra chars that has been added to the new array.
#include <stdio.h>
#define MAX_LEN 20
int main(void) {
char org_arr[MAX_LEN] = "aabbcc";
char new_arr[MAX_LEN] = {0};
int char_added = 0;
int idx = 1;
new_arr[0] = org_arr[0];
if (new_arr[0])
{
while(org_arr[idx])
{
if (org_arr[idx] == org_arr[idx-1])
{
new_arr[idx + char_added] = '*';
++char_added;
}
new_arr[idx + char_added] = org_arr[idx];
++idx;
}
}
puts(new_arr);
return 0;
}
Output:
a*ab*bc*c
Note: The code isn't fully tested. Also it lacks out-of-bounds checking.
There is a lot left to be desired in your Minimal, Complete, and Verifiable Example (MCVE) (MCVE). However, that said, what you will need to do is fairly straight-forward. Take a simple example:
"ssi"
According to your statement, you need to add a character between the adjacent 's' characters. (you can use whatever you like for the separator, but if your input are normal ASCII character, then you can set the current char to the next ASCII character (or subtract one if current is the last ASCII char '~')) See ASCII Table and Description.
For example, you could use memmove() to shift all characters beginning with the current character up by one and then set the current character to the replacement. You also need to track the current length so you don't write beyond your array bounds.
A simple function could be:
#include <stdio.h>
#include <string.h>
#define MAXC 1024
char *betweenduplicates (char *s)
{
size_t len = strlen(s); /* get length to validate room */
if (!len) /* if empty string, nothing to do */
return s;
for (int i = 1; s[i] && len + 1 < MAXC; i++) /* loop until end, or out of room */
if (s[i-1] == s[i]) { /* adjacent chars equal? */
memmove (s + i + 1, s + i, len - i + 1); /* move current+ up by one */
if (s[i-1] != '~') /* not last ASCII char */
s[i] = s[i-1] + 1; /* set to next ASCII char */
else
s[i] = s[i-1] - 1; /* set to previous ASCII char */
len += 1; /* add one to len */
}
return s; /* convenience return so it can be used immediately if needed */
}
A short example program taking the string to check as the first argument could be:
int main (int argc, char **argv) {
char str[MAXC];
if (argc > 1) /* if argument given */
strcpy (str, argv[1]); /* copy to str */
else
strcpy (str, "mississippi"); /* otherwise use default */
puts (str); /* output original */
puts (betweenduplicates (str)); /* output result */
}
Example Use/Output
$ ./bin/betweenduplicated
mississippi
mistsistsipqpi
or when there is nothing to replace:
$ ./bin/betweenduplicated dog
dog
dog
Or checking the extremes:
$ ./bin/betweenduplicated "two spaces and alligators ~~"
two spaces and alligators ~~
two ! spaces ! and ! almligators ! ~}~
There are a number of ways to approach it. Let me know if you have further questions.

How to rearrange array using spaces?

I'm struggling with rearranging my array. I have used from single to multiple loops trying to put spaces (white characters) between two pairs of characters, but I was constantly rewriting the original input. So there is always an input of even length, for example ABCDEFGH. And my task would be to extend the size of the array by putting spaces after every 2 chars (except the last one).
So the output would be:
AB CD EF GH
So the size of output (if I'm correct) will be (2*input_len)-1
Thanks.
EDIT:
This is my code so far
// output = "ABCDEFGHIJKL
char c1;
char c2;
char c3;
int o_len = strlen(output);
for(int i = 2; i < o_len + olen/2; i = i + 3){
if(i == 2){
c1 = output[i];
c2 = output[i+1];
c3 = output[i+2];
output[i] = ' ';
output[i+1] = c1;
output[i+2] = c2;
}
else{
c1 = output[i];
c2 = output[i+1];
output[i] = ' ';
output[i+1] = c3;
output[i+2] = c1;
c3 = c2;
}
}
So the first 3 pairs are printed correctly, then it is all a mess.
Presuming you need to store the space separate result, probably the easiest way to go about inserting the spaces is simply to use a pair of pointers (one to your input string and one to your output string) and then just loop continually writing a pair to your output string, increment both pointers by 2, check whether you are out of characters in your input string (if so break; and nul-terminate your output string), otherwise write a space to your output string and repeat.
You can do it fairly simply using memcpy (or you can just copy 2-chars to the current pointer and pointer + 1, your choice, but since you already include string.h for strlen() -- make it easy on yourself) You can do something similar to:
#include <stdio.h>
#include <string.h>
#define ARRSZ 128 /* constant for no. of chars in output string */
int main (int argc, char **argv) {
char *instr = argc > 1 ? argv[1] : "ABCDEFGH", /* in string */
outstr[ARRSZ] = "", /* out string */
*ip = instr, *op = outstr; /* pointers to each */
size_t len = strlen (instr); /* len of instr */
if (len < 4) { /* validate at least 2-pairs worth of input provided */
fputs ("error: less than two-pairs to separate.\n", stderr);
return 1;
}
if (len & 1) { /* validate even number of characters */
fputs ("error: odd number of characters in instr.\n", stderr);
return 1;
}
if (ARRSZ < len + len / 2) { /* validate sufficient storage in outstr */
fputs ("error: insufficient storage in outstr.\n", stderr);
return 1;
}
for (;;) { /* loop continually */
memcpy (op, ip, 2); /* copy pair to op */
ip += 2; /* increment ip by 2 for next pair */
op += 2; /* increment op by 2 for next pair */
if (!*ip) /* check if last pair written */
break;
*op++ = ' '; /* write space between pairs in op */
}
*op = 0; /* nul-terminate outstr */
printf ("instr : %s\noutstr : %s\n", instr, outstr);
}
Example Use/Output
$ ./bin/strspaceseppairs
instr : ABCDEFGH
outstr : AB CD EF GH
$ ./bin/strspaceseppairs ABCDEFGHIJLMNOPQ
instr : ABCDEFGHIJLMNOPQ
outstr : AB CD EF GH IJ LM NO PQ
Odd number of chars:
$ ./bin/strspaceseppairs ABCDEFGHIJLMNOP
error: odd number of characters in instr.
Or short string:
$ ./bin/strspaceseppairs AB
error: less than two-pairs to separate.
Look things over and let me know if you have further questions.
Edit To Simply Output Single-Pair or Empty-String
Based upon the comment by #chqrlie it may make more sense rather than issuing a diagnostic for a short string, just to output it unchanged. Up to you. You can modify the first conditional and move it after the odd character check in that case, e.g.
if (len & 1) { /* validate even number of characters */
fputs ("error: odd number of characters in instr.\n", stderr);
return 1;
}
if (len < 4) { /* validate at least 2-pairs worth of input provided */
puts(instr); /* (otherwise output unchanged and exit) */
return 0;
}
You can decide how you want to handle any aspect of your program and make the changes accordingly.
I think you are looking for a piece of code like the one below:
This function returns the output splitted array, as you requested to save it.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
char* split_by_space(char* str, size_t length, size_t step) {
size_t i = 0, j = 0, spaces = (length / step);
char* splitted = malloc(length + spaces + 1);
for (i = 0, j = 0; i < length; ++i, ++j) {
if (i % step == 0 && i != 0) {
splitted[j] = ' ';
++j;
}
splitted[j] = str[i];
}
splitted[j] = '\0';
return splitted;
}
int main(void) {
// Use size_t instead of int.
size_t step = 2; // Also works with odd numbers.
char str[] = "ABCDEFGH";
char* new_str;
// Works with odd and even steps.
new_str = split_by_space(str, strlen(str), step);
printf("New splitted string is [%s]", new_str);
// Don't forget to clean the memory that the function allocated.
free(new_str);
return 0;
}
When run with a step value of 2, the above code, outputs:
New splitted string is [AB CD EF GH]
Inserting characters inside the array is cumbersome and cannot be done unless you know the array is large enough to accommodate the new string.
You probably want to allocate a new array and create the modified string there.
The length of the new string is not (2 * input_len) - 1, you insert a space every 2 characters, except the last 2: if the string has 2 or fewer characters, its length is unmodified, otherwise it increases by (input_len - 2) / 2. And in case the length is off, you should round this value to the next integer, which is done in integer arithmetics this way: (input_len - 2 + 1) / 2.
Here is an example:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *reformat_with_spaces(const char *str) {
size_t len = strlen(str);
size_t newlen = len > 2 ? len + (len - 2 + 1) / 2 : len;
char *out = malloc(newlen + 1);
if (out) {
for (size_t i = 0, j = 0; i < len; i++) {
if (i > 0 && i % 2 == 0) {
out[j++] = ' ';
}
out[j++] = str[i];
}
out[j] = '\0';
}
return out;
}
int main(void) {
char buf[256];
char *p;
while (fgets(buf, sizeof buf, stdin)) {
buf[strcspn(buf, "\n")] = '\0'; // strip the newline if any
p = reformat_with_spaces(buf);
if (p == NULL) {
fprintf(stderr, "out of memory\n");
return 1;
}
puts(p);
free(p);
}
return 0;
}
Try this,
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void rearrange(char *str)
{
int len=strlen(str),n=0,i;
char *word=malloc((len+(int)(len/2)));
if(word==NULL)
{
printf("Memory Error");
exit(1);
}
for(i=0;i<len;i++)
{
if( i % 2 == 0 && i != 0)
{
word[n]=' ';
n++;
word[n]=str[i];
n++;
}
else
{
word[n]=str[i];
n++;
}
}
word[n]='\0';
strcpy(str,word);
free(word);
return;
}
int main()
{
char word[40];
printf("Enter word:");
scanf("%s",word);
rearrange(word);
printf("\n%s",word);
return 0;
}
See Below:
The rearrange function saves the letters in str into word. if the current position is divisible by 2 i.e i%2 it saves one space and letter into str, otherwise it saves letter only.

Printing an entire character array after looping through every point in a rectangular area

I'm using a double for-loop in order to check every point (coordinate pair) in a rectangular area from (-2.0, -1.12) to (0.47, 1.12) to see whether it belongs to the Mandelbrot set. If it does, I want to print a 1. Likewise, if it does not, I want to print a 0. The basic idea is to print, line by line, an array of characters that displays a simplified Mandelbrot set.
This is my main function:
#include <stdio.h>
#include "complex.h"
#include "mandelbrot.h"
#define STEP_X 0.06175
#define STEP_Y 0.07466
int main(void){
int i = 0;
char arr[50];
complex_t c, abs, max;
max.real = 10000;
max.imag = 0;
for (c.imag = -1.12; c.imag <= 1.12; c.imag += STEP_Y){
for (c.real = -2.0; c.real <= 0.47; c.real += STEP_X){
abs = abs_complex(mandelbrot(c,15));
if (abs.real < max.real){
arr[i] = 1;
i++;
}
else{
arr[i] = 0;
i++;
}
}
printf("%s", arr);
i = 0;
}
}
The program compiles just fine, but does not produce an output. I know I must not be printing the array the right way, but for the life of me I can not figure out how to do it.
Any feedback, hints, or tips would be greatly appreciated.
Thanks in advance!
The problems you are having are two-fold. (1) you are copying decimal values to arr (e.g. 0 and 1) instead of ASCII characters ('0' and '1'). Decimal 0 and 1 are non-printable. Ironically decimal 0 is the nul-terminating character, so if if (abs.real >= max.real) for i == 0 arr holds the empty-string.
Second you call printf without having insured the final character is the nul-terminating character. (you can do this by default by initializing char arr[MAXC] = ""; and insuring your loop is limited to i + 1 < 50 && c.real <= 0.47 or you can simply affirmatively terminate arr with arr[i] = 0; before calling i = 0; (or move your declaration of i inside the first for loop and initialize).
This is untested (I don't have your local headers), but it looks like you intended:
#include <stdio.h>
#include "complex.h"
#include "mandelbrot.h"
#define MAXC 50
#define STEP_X 0.06175
#define STEP_Y 0.07466
int main(void){
complex_t c, abs, max;
max.real = 10000;
max.imag = 0;
for (c.imag = -1.12; c.imag <= 1.12; c.imag += STEP_Y) {
int i = 0; /* declare/initialize i & arr here */
char arr[MAXC] = ""; /* set to all zero */
for (c.real = -2.0;
i + 1 < MAXC && c.real <= 0.47; /* limit to 49 chars max */
c.real += STEP_X) {
abs = abs_complex (mandelbrot (c,15));
if (abs.real < max.real)
arr[i++] = '1'; /* assign character '1' */
else
arr[i++] = '0'; /* assign character '0' */
}
arr[i] = 0; /* nul-terminate line */
printf ("%s\n", arr); /* output line */
}
return 0;
}
Give it a try and let me know if you have further questions.

How to get rid of garbage characters in this program?

This program is supposed to print an input string backwards. Every single time it happens, though, I get garbage characters such as \340 or of the like. Why is it doing that? Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char mattsentence[51];
mattsentence[50] = '\0';
gets(mattsentence);
char mask[sizeof(mattsentence)];
int i, j;
j = sizeof(mattsentence);
for (i = 0; i < sizeof(mask); i++)
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
printf("\n");
}
Your approach is wrong because you reverse the entire character array while it can be filled only partially. You should use standard C function strlen declared in header <string.h> that to determine the size of the entered string. Also to use gets is unsafe because you can overwrite memory beyond the character array. It now is excluded from the C Standard
Here is shown how the program can be written.
#include <stdio.h>
#include <string.h>
#define N 51
int main(void)
{
char mattsentence[N] = { '\0' };
char mask[N] = { '\0' };
fgets( mattsentence, sizeof( mattsentence ), stdin );
size_t n = strlen( mattsentence );
if ( n != 0 && mattsentence[n-1] == '\n' ) mattsentence[--n] = '\0';
for ( size_t i = 0; n != 0; i++ )
{
mask[i] = mattsentence[--n];
printf( "%c", mask[i] );
}
printf( "\n" );
return 0;
}
If to enter
Hello, Christiana S. F. Chamon
then the program output will be
nomahC .F .S anaitsirhC ,olleH
Take into account that to output a string in the reverse order there is no need to define a second character array.
If you want only to output the source string in the reverse order then the program can look like
#include <stdio.h>
#include <string.h>
#define N 51
int main(void)
{
char mattsentence[N] = { '\0' };
fgets( mattsentence, sizeof( mattsentence ), stdin );
size_t n = strlen( mattsentence );
if ( n != 0 && mattsentence[n-1] == '\n' ) mattsentence[n-1] = '\0';
while ( n != 0 )
{
printf( "%c", mattsentence[--n] );
}
printf( "\n" );
return 0;
}
sizeof() operator gives the size of the datatype. So, sizeof(mattsentence) will give you a value of 51. Then, sizeof(mask) will give you 51 again.
When you use that sizeof(mask) as for loop condition, you're basically going past the actual input values, thus pritning out garbage values.
What you want here is to use strlen() to find out the actual valid length of the entered string.
So, basically you need to take care of
Point 1: replace sizeof with strlen().
Point 2: Use of gets() is dangerous. Please use fgets() instead of gets().
Point 3: int main() should be int main(void). Put an expilicit return statement at the end of main(). Good Practice.
The modified code should look like
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char mattsentence[51] = {0}; //always initalize local variables, here it's covering null termination , too.
fgets(mattsentence, 51, stdin); //fgets()
char mask[strlen(mattsentence) + 1]; // one more to store terminating '\0'
int i = 0, j = 0, k = 0;
j = strlen(mattsentence);
k = j;
for (i = 0; i < k; i++) // make use of k, don't call `strlen()` repeatedly
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
mask[i] = '\0'; // for proper string termination
printf("\n");
printf("%s\n", mask);
return 0; //added return statement
}
See changed code:
int main()
{
char mattsentence[51];
mattsentence[0] = '\0'; // initialization
gets(mattsentence);
char mask[strlen(mattsentence) + 1]; // +1 for string terminator '\0'
int i, j;
j = strlen(mattsentence);
for (i = 0; i < strlen(mattsentence); i++) // strlen of original string
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
mask[i] = '\0'; // for proper string termination
printf("\n");
printf("%s\n", mask);
}
There are several errors:
strlen() should be used to get length of string
for loop should be controlled according to input string, not output string
it is better to use fgets() instead of gets(): that way you can control how many character will be read from the input

Resources