Array Input off by one index in C. Caesar Block Shift - c

Here I have code that inputs from stdin a stream of characters into an array. It then converts that array to a 2d array. Then it changes that array from row column order to column row order. Then it prints out the new array creating a Caesar shift encryption. The issue I am having is that my array is starting to input characters into the array with the second user typed character and I am not sure why.
For Example, if I type "Hello" into the console, only "ello" is put into the array.
Any thoughts? Thanks!
//
// main.c
// Caesar Block Cypher
//
// Created by Jacob Byerline on 10/20/18.
// Copyright © 2018 Jacob Byerline. All rights reserved.
//
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
int main(void){
//The size is extended by the input with the value of the provisional
char *str;
int inputChar;
int i, j;
size_t size = 0;
size_t len = 0;
printf("input string : ");
inputChar = getchar();
str = realloc(NULL, sizeof(char)*size);//size is start size
if(!str)return *str;
while(EOF!=(inputChar=fgetc(stdin)) && inputChar != '\n'){
if(isalpha(inputChar)){
str[len++]=inputChar;
if(len==size){
str = realloc(str, sizeof(char)*(size+=16));
if(!str)return *str;
}
}
}
str[len++]='\0';
int squareOfLen = sqrt(len);
int twoDimensionalArraySize = squareOfLen + 1;
//printf("%lu \n", len);
//printf("%d \n", squareOfLen);
//printf("%d \n", twoDimensionalArraySize);
char twoDstr[twoDimensionalArraySize][twoDimensionalArraySize];
char FINALtwoDstr[twoDimensionalArraySize][twoDimensionalArraySize];
memcpy(twoDstr, str, twoDimensionalArraySize * 2 * sizeof(int));
for(i=0; i<twoDimensionalArraySize; i++){
for(j=0; j<twoDimensionalArraySize; j++){
printf("2D Array[%d][%d] = %c\n",i,j,twoDstr[i][j]);
}
}
for(i=0; i<twoDimensionalArraySize; i++){
for(j=0; j<twoDimensionalArraySize; j++){
FINALtwoDstr[i][j] = twoDstr[j][i];
//printf("2D Array[%d][%d] = %c\n",i,j,FINALtwoDstr[i][j]);
printf("%c",FINALtwoDstr[i][j]);
}
}
printf("\n");
return 0;
}

Remove
inputChar = getchar();
This is taking up 'H' from your input stream.
See here https://ideone.com/ZwT9Iq
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
int main(void){
//The size is extended by the input with the value of the provisional
char *str;
int inputChar;
int i, j;
size_t size = 0;
size_t len = 0;
printf("input string : ");
//inputChar = getchar();
str = realloc(NULL, sizeof(char)*size);//size is start size
if(!str)return *str;
while(EOF!=(inputChar=fgetc(stdin)) && inputChar != '\n'){
if(isalpha(inputChar)){
str[len++]=inputChar;
if(len==size){
str = realloc(str, sizeof(char)*(size+=16));
if(!str)return *str;
}
printf("%c", inputChar);
}
}
printf("\n");
str[len]='\0';
int squareOfLen = sqrt(len);
int twoDimensionalArraySize = squareOfLen + 1;
//printf("%lu \n", len);
//printf("%d \n", squareOfLen);
//printf("%d \n", twoDimensionalArraySize);
char twoDstr[twoDimensionalArraySize][twoDimensionalArraySize];
char FINALtwoDstr[twoDimensionalArraySize][twoDimensionalArraySize];
memcpy(twoDstr, str, twoDimensionalArraySize * 2 * sizeof(int));
for(i=0; i<twoDimensionalArraySize; i++){
for(j=0; j<twoDimensionalArraySize; j++){
printf("2D Array[%d][%d] = %c\n",i,j,twoDstr[i][j]);
}
}
for(i=0; i<twoDimensionalArraySize; i++){
for(j=0; j<twoDimensionalArraySize; j++){
FINALtwoDstr[i][j] = twoDstr[j][i];
//printf("2D Array[%d][%d] = %c\n",i,j,FINALtwoDstr[i][j]);
printf("%c",FINALtwoDstr[i][j]);
}
}
printf("\n");
return 0;
}
output
Hleol

Ignoring allocation and check for alpha-ness, you do this:
inputChar = getchar(); // Read first char
while (EOF != (inputChar=fgetc(stdin)) // read further chars
&& inputChar != '\n') {
str[len++]=inputChar;
}
That means that the first character is consumed, but never stored. Instead, you could do this:
inputChar = getchar(); // Read first char
while (inputChar != EOF && inputChar != '\n') {
str[len++]=inputChar;
inputChar=fgetc(stdin) // read further chars
}
But there are other issues with your code:
You start with an allocation of zero bytes, because size is 0;
You should allocate before you store, otherwise you write beyond the end of the buffer;
When you add the null terminator, you probably shouldn't increase len, because the '\0' isn't part of the locical length of the string, even if you have to allocate space for it, which you don't in all cases;
The square of len is len * len, not sqrt(len): That's the square root;
You square the dimension twice: If len is 3, you want an 3×3 array, but you try to allocate a 9×9 array on the stack;
You can't copy len*len * 2 * sizeof(int) bytes from str, which has only len bytes.
There's probably more in the last part; I haven't looked too closely.

Related

Print a string from a pointer in C

I have a dynamically sized CHARS array, I'm trying to print the string, using pointers.
I tried something like this:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main(){
char *str = NULL;
int size = 0;
int c, i;
printf("Please enter your command\n");
while((c = getchar()) != EOF)
{
str = (char *)realloc(str, size + 1);
str[size++] = c;
}
str = (char *)realloc(str, size + 1);
str[size] = '\0';
free(str);
printf("\nThe size is %d\n", size);
/* here I want to print the string */
for(i = *str; i!='\0'; i++){
printf("%c", *str+i);
}
return 0;
}
This code does not print the string. The topic of using pointers is not really clear to me, so I think there is my mistake.
You deallocated early allocated memory
free(str);
So after this statement the pointer str is invalid and accessing memory using the pointer invokes undefined behavior. You need to free the memory when the allocated character array will not be required any more.
This for loop
/* here I want to print the string */
for(i = *str; i!='\0'; i++){
printf("%c", *str+i);
}
does not make sense. In this for loop the variable i that stores the code of the first character of the string stored in the dynamically allocated array is incremented. For example if the first character of the string is 'A' that is in ASCII 65 then after the first iteration it will be equal to 66 that corresponds to the character 'B'. And the expression *str + i will look like 'A' + 'B' that is the same as 65 + 66.
If you are going to outputted the stored string using a pointer then you should write for example
/* here I want to print the string */
for ( const char *p = str; *p != '\0'; ++p ){
printf("%c", *p);
}
putchar( '\n' );
You need to free the memory when you do not need it anymore.
Move free(str) to the end of main.
Also printf("%c", *str+i); is wrong. You need to printf("%c", *(str+i));
You do not check the result of realloc.
char *tmp;
tmp = realloc(str, size + 1);
if(tmp)
{
str = tmp;
str[size++] = c;
}
else
{
/* handle error */
}
+++ more issues so I will post the working code:
int main(void){
char *str = NULL;
size_t size = 0;
int c;
size_t i;
printf("Please enter your command\n");
while((c = getchar()) != EOF)
{
char *tmp;
tmp = realloc(str, size + 2);
if(tmp)
{
str = tmp;
str[size++] = c;
}
else
{
return 1;
}
}
str[size] = '\0';
printf("\nThe size is %zu\n", size);
/* here I want to print the string */
for(i = 0; str[i]; i++){
printf("%c", *(str+i));
}
free(str);
return 0;
}

Trying to "copy" one string in reverse

I've been trying to "copy" one string to another, in reverse.
It kindof works, but it prints some weird symbols.
I've tried setting char copy[length2] but that makes the program not run at all.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define ARR_SIZE 50
int main()
{
char string[ARR_SIZE];
printf("Enter char array!\n");
fgets(string, ARR_SIZE, stdin);
string[strlen(string) - 1] = '\0';
int length = (strlen(string) - 1);
int length2 = (strlen(string) - 1);
printf("%s\t%d\n", string, length);
for (int i = 0; i <= length; i++)
{
printf("INDEX = %d CHAR = %c\n", i, string[i]);
}
printf("%d", length2);
char copy[ARR_SIZE];
for (int i = 0; i <= length2; i++)
{
copy[i] = string[length];
length--;
}
printf("\n%s", copy);
}
These are the minimal modifications I'd make to your code:
#include <stdio.h>
#include <string.h>
// remove unneeded headers
#define ARR_SIZE 50
int main(void)
{
char string[ARR_SIZE];
printf("Enter char array!\n");
fgets(string, ARR_SIZE, stdin);
string[strlen(string) - 1] = '\0';
// remove the -1 on the string length calculation, the NUL terminator is not
// included in strlen's return value
int length = strlen(string);
// no sense in calling strlen twice
int length2 = length;
// fixed `length` now prints the correct length
printf("%s\t%d\n", string, length);
// change from <= to <. The array indices where the characters live are
// [0, length-1].
for (int i = 0; i < length; i++)
{
printf("INDEX = %d CHAR = %c\n", i, string[i]);
}
// fixed `length2` now prints the correct length
printf("%d", length2);
char copy[ARR_SIZE];
for (int i = 0; i < length2; i++)
{
// last character in `string` lives at the `length`-1 index
copy[i] = string[length-1];
length--;
}
// `length2` is the index after the last char in `copy`, this needs
// to be NUL terminated.
copy[length2] = '\0';
// prints the reversed string
printf("\n%s", copy);
}
Demo
Use functions.
Terminate strings with null character \0 or simply 0.
char *copyreverse(char *dest, const char *src)
{
size_t len = strlen(src);
const char *end = src + len - !!len;
char *wrk = dest;
while(len--)
*wrk++ = *end--;
*wrk = 0;
return dest;
}
int main()
{
char dest[10];
char *src = "hello";
printf("`%s` reversed `%s`\n", src, copyreverse(dest, src));
}

How to print length of each word in a string before the each Word

I want to print the length of each word in a string.
I have tried but not getting right answer. After running the code it will print the length of each word after the word instead of printing before the each word.
char str[20] = "I Love India";
int i, n, count = 0;
n = strlen(str);
for (i = 0; i <= n; i++) {
if (str[i] == ' ' || str[i] == '\0') {
printf("%d", count);
count = 0;
} else {
printf("%c", str[i]);
count++;
}
}
I except the output is 1I 4Love 5India, but the actual output is I1 Love4 India5.
You can use strtok as Some programmer dude sugested. You may want to make a copy of the original string as strtok modifies the passed string. Also strtok is not thread-safe and must be replaced with strtok_r when working with multi-threaded programs.
#include <stdio.h>
#include <stdlib.h>
/* for strtok */
#include <string.h>
int main() {
char str[20] = "I Love India";
int n;
char* tok = strtok(str, " ");
while (tok != NULL) {
n = strlen(tok);
printf("%d%s ", n, tok);
tok = strtok(NULL, " ");
}
return EXIT_SUCCESS;
}
You want to compute and print the length of each word before you print the word.
Here is a simple solution using strcspn(), a standard function that should be used more often:
#include <stdio.h>
#include <string.h>
int main() {
char str[20] = "I Love India";
char *p;
int n;
for (p = str; *p;) {
if (*p == ' ') {
putchar(*p++);
} else {
n = strcspn(p, " "); // compute the length of the word
printf("%d%.*s", n, n, p);
p += n;
}
}
printf("\n");
return 0;
}
Your approach is wrong as you print the word before the length. So you need to calculate the length first then print it and then print the word.
It could be something like:
int main(void)
{
char str[20]="I Love India";
size_t i = 0;
while(str[i])
{
if (str[i] == ' ') // consider using the isspace function instead
{
// Print the space
printf(" ");
++i;
}
else
{
size_t j = i;
size_t count = 0;
// Calculate word len
while(str[j] && str[j] != ' ')
{
++count;
++j;
}
// Print word len
printf("%zu", count);
// Print word
while(i<j)
{
printf("%c", str[i]);
++i;
}
}
}
}
The basic idea is to have two index variables for the string, i and j. The index i is at the words first character and index j is used for finding the end of the word. Once the end of word has been found, the length and the word can be printed.
This is what you want:
#include <stdio.h>
#include <string.h>
int main()
{
char str[20]="I Love India";
char buf[20];
int i,n,count=0;
n=strlen(str);
for (i=0; i <= n; i++) {
if(str[i]==' ' || str[i]=='\0'){
buf[count] = '\0';
printf("%d", count); /* Print the size of the last word */
printf("%s", buf); /* Print the buffer */
memset(buf, 0, sizeof(buf)); /* Clear the buffer */
count = 0;
} else {
buf[count] = str[i];
count++;
}
}
return 0;
}
You will want to keep a buffer of the word that is currently being counted. (buf)
Increment count each time its not a space or 0/. Then, when it is a space or a 0/, print count first, then buf. Then, we will clear buf and set count to 0, so that the variable i is still incrementing through the entire string str, but we are inserting the words into buf starting from 0.

Reading words from the keyboard and puting them in a Matrix

I have to read 5 words from the keyboard and put them in a matrix. For example if I have the word RED, the letters will be split between the columns of the first row. R E D and so on.
This is my code but it exits after I scanf 5 letters
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
char mat[3][3];
for(int i=0; i<2; i++)
for(int j=0;j<2;j++)
{
scanf("%s", &mat[i][j]);
}
for(int i=0; i<2; i++)
for(int j=0;j<2;j++)
{
printf("%s\t",mat[i][j]);
}
return 0;
}
Since you haven't specified any size for the strings... I will presume they are of arbitrary length...
// Takes input using the 'stdin' stream...
char* read_input(void)
{
char ch;
size_t len = 0;
size_t size = len + 2;
char* str = realloc(NULL, size);
if (!str)
return str;
while ((ch = fgetc(stdin)) != -1 && ch != '\n')
{
str[len++] = ch;
if (len == size)
{
str = realloc(str, size += 2);
if (!str)
return str;
}
}
str[len++] = '\0';
return realloc(str, len);
}
This function will read the input, now we also need a function for checking if the string is a valid word... i.e, it contains only alphabets...
// Checks whether the specified string is alphabetic or not...
int is_alpha_string(char* str, char* err_msg)
{
for (unsigned i = 0u; i < strlen(str); i++)
if (!isalpha(str[i]))
{
fprintf(stderr, err_msg);
return 0;
}
return 1;
}
After this, just do:
// The 'main()' function...
int main(void)
{
char* matrix[5];
for (unsigned i = 0u; i < 5u; i++)
{
printf("Enter your word here: ");
matrix[i] = read_input();
i -= !is_alpha_string(matrix[i], "Error! Entered text is not a valid word!\n\n");
}
for (int i = 0; i < 5; i++)
printf("%s\n", matrix[i]);
return 0;
}
Edit: And don't forget to add these includes at the top:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

Replacing character in a string [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the function to replace string in C?
I am trying to replace a certain character in my string with multiple characters. Here is an example of what I am trying to do.
Say I have the string "aaabaa"
I want to replace all occurrences of the character "b" with 5 "c"s.
So when I am done, "aaabaa" becomes "aaacccccaa"
I have written the following code:
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[20] = "aaabaa";
int i, j;
for (i=0; s[i]!= '\0'; i++)
{
if (s[i] == 'b')
{
for (j=0; j<5; j++)
{
s[i+j] = 'c';
}
}
}
printf("%s\n", s);
}
My output from this function is "aaaccccc". It appears that it just overwrites the last two a's with the c's. Is there any way I would have it so that these last couple of a's dont get overwritten?
If you want to do this in general, without worrying about trying to size your buffers, you should malloc a new string just large enough to hold the result:
/* return a new string with every instance of ch replaced by repl */
char *replace(const char *s, char ch, const char *repl) {
int count = 0;
const char *t;
for(t=s; *t; t++)
count += (*t == ch);
size_t rlen = strlen(repl);
char *res = malloc(strlen(s) + (rlen-1)*count + 1);
char *ptr = res;
for(t=s; *t; t++) {
if(*t == ch) {
memcpy(ptr, repl, rlen);
ptr += rlen;
} else {
*ptr++ = *t;
}
}
*ptr = 0;
return res;
}
Usage:
int main() {
char *s = replace("aaabaa", 'b', "ccccc");
printf("%s\n", s);
free(s);
return 0;
}
Your problem is that you replace the "ccccc" into the original string thus overwriting the remaining characters after what you wish to replace... You should copy into a new string and keep track of two indices - one in each.
And be happy that you declared char s[20] larger than the size of your original string plus the replace values, as otherwise you'd have created a buffer overflow vulnerability in your critical login system :-)
Cheers,
It is necessary to declare a second char array. In below code it just copies content of array s to s1 when condition fails.
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[20] = "aaabaa";
char s1[1024];
int i, j, n;
for (i=0, n = 0; s[i]!= '\0'; i++)
{
if (s[i] == 'b')
{
for (j=0; j<5; j++)
{
s1[n] = 'c';
n++;
}
}
else
{
s1[n] = s[i];
n++;
}
}
s1[n] = '\0';
printf("%s\n", s1);
}
You can use a different variable
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[20] = "aaabaa";
char temp[20]="";
int i, j,k;
k=0;
for (i=0; s[i]!= '\0'; i++)
{
if (s[i] == 'b')
{
for (j=0; j<5; j++)
{
temp[k] = 'c';
k++;
}
}
else
{
temp[k]=s[i];
k++
}
}
printf("%s\n", temp);
}
#include <stdio.h>
#include <string.h>
int main(void)
{
char temp[20];
char s[20] = "aaabaa";
int i, j;
for (i=0; s[i]!= '\0'; i++)
{
if (s[i] == 'b')
{
strcpy(temp,s[i+1]); //copy rest of the string in this case 'aa'
for (j=0; j<5; j++)
{
s[i+j] = 'c';
}
s[i+j] = '\0'; // here we get s = "aaaccccc"
strcat(s,temp); // concat rest of the string (temp = "aa") after job is done.
// to this point s becomes s = "aaacccccaa"
}
}
printf("%s\n", s); //s = "aaacccccaa".
}
here we are using a buffer (temp) to store the rest of the string after our to be replaced character.
after the replacement is done we append it to the end.
so we get s = "aaacccccaa"
Well, if you're going to dynamically allocate the array, you will probably have to allocate a second array. This is necessary because your string s only has a fixed amount of memory allocated.
So, instead of tryig to overwrite the characters in your for loop, I would suggest incrementing a counter that told you how big your new array has to be. Your counter should start off as the size of your original string and increment by 4 each time an instance of 'b' is found. You should then be able to write a function that appropriately copies the modified string over to a new char buffer of size[counter], inserting 5 c's every time a 'b' is being found.
Use this function :
char *replace(char *st, char *orig, char *repl) {
static char buffer[4096];
char *ch;
if (!(ch = strstr(st, orig)))
return st;
strncpy(buffer, st, ch-st);
buffer[ch-st] = 0;
sprintf(buffer+(ch-st), "%s%s", repl, ch+strlen(orig));
return buffer;
}
for your case : printf("%s\n", replace(s,"b","ccccc"));

Resources