Having troubles understanding string declaration in C - c

I'm having some trouble understanding a string declaration in C using dynamic memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *putText(){
char *s=(char *) malloc(256+sizeof(char));
for(int i=0; *(s+i); i++) *(s+i)=getchar();
return s;
}
void main(){
printf("Write the text: ");
char *s=putText();
printf("%s", s);
}
In this function, I'm trying to declare the string using getchar() in a for loop, but when I try to print the string, it always stops at the third character.
I am still a newbie, so I've probably made some mistake. Can someone help?

The allocated memory in this declaration
char *s=(char *) malloc(256+sizeof(char));
can contain any garbage.
So the condition in the for loop
for(int i=0; *(s+i); i++) *(s+i)=getchar();
does not make a sense.
Instead you could write for example
int c;
for ( size_t i=0; i + 1 < 256 && ( c = getchar() ) != EOF && c != '\n'; i++ )
{
*( s + i ) = c;
}
*( s + i ) = '\0';

Related

I am writing C function that convert lowercase char to upper case char with using ASCII but Output is not correct

Okay, So I start working on this, I have code below;
+I also have strlen("any string here") func that return len of any str in decimal just keep in your mind.
I take a lover case let's say a, then a will be equal some decimal num in ASCII table then I subtract 32 to get A.
Sadly this is not working, any idea for this?
Thank you for all help and your time!
int uppercase(char sent[]) {
for(int i=0; i <= strlen(sent); ++i) {
if(sent[i]>='a' && sent[i]<='z')
sent[i] -= 32;
}
The function is declared as having the return type int but returns nothing.
int uppercase(char sent[]) {
for(int i=0; i <= strlen(sent); ++i) {
if(sent[i]>='a' && sent[i]<='z')
sent[i] -= 32;
}
In general for a function that deals with strings the condition of the for loop should look at least like
for(int i=0; i < strlen(sent); ++i) {
Though it is better to write the loop like
for( size_t i = 0, n = strlen(sent); i < n; ++i ) {
However there is no great sense to use the function strlen in the function uppercase. Its call is redundant.
Pay attention to that you may not change a string literal. Any attempt to change a string literal results in undefined behavior.
From the C Standard (6.4.5 String literals)
7 It is unspecified whether these arrays are distinct provided their
elements have the appropriate values. If the program attempts to
modify such an array, the behavior is undefined.
Also it is better not to use the magic number 32.
The function can be written the following way as it is shown in the demonstrative program below.
#include <stdio.h>
char * uppercase( char *s )
{
for ( char *p = s; *p; ++p )
{
if ( 'a' <= *p && *p <= 'z' ) *p = *p & ~' ';
}
return s;
}
int main(void)
{
char s[] = "hello world!";
puts( s );
puts( uppercase( s ) );
return 0;
}
The program output is
hello world!
HELLO WORLD!
As for the function strlen then it is better to use another name for the function because it will conflict with the standard C function strlen. And the function itself can be defined the following way
size_t string_len( const char *s )
{
const char *p = s;
while ( *p ) ++p;
return p - s;
}
This code can help you
#include <stdio.h>
#include <string.h>
void uppercase(char T[],int k)
{
int i=0;
while(i<k)
{
if(T[i]>='a'&&T[i]<='z')
{
T[i]=(char)((int)T[i]-32);
}
i++;
}
i=0;
while(i<k)
{
printf("%c",T[i]);
i++;
}
printf("\n");
}
int main()
{
char T[]="good morning !";
int k=sizeof(T);
uppercase(T,k);
}
This one will work:
#include <stdio.h>
#include <string.h>
void uppercase(char sent[]) {
for (int i = 0; i < (int)strlen(sent); i++) {
if (sent[i] >= 'a' && sent[i] <= 'z') {
sent[i] -= 32;
}
}
}
int main(int argc, char* argv[]) {
if (argc > 1){
uppercase(argv[1]);
puts(argv[1]);
}
return 0;
}
It compiles without any errors and warnings (using clang), even with options -pedantic -Wall -Wextra.
/*
Parsing the string, then making the letters to uppercase.
*/
#include <stdio.h>
#include <limits.h>
int strlen(char s[]){ //String length function
int i;
for (i = 0; s[i] != '\0'; i++);
return i;
}
void uppercase(char sent[]) {
for(int i=0; i < strlen(sent); ++i) {
if(sent[i]>='a' && sent[i]<='z')
sent[i] += 32;
}
printf("%s", sent);
}
this is a whole tab of my whole work. when i try uppercase("hello world"); it giving me core dumped console problem.

Why is my program to reverse its input a line at a time not working?

I was trying to write a program that reverses its input a line at a time. I thought I had done it successfully, however it sometimes doesn't give the desirable output (this happens when I put an input with a smaller length than the one I put previously). I am new to this and I was wondering what can I do to solve this issue.
Program:
#include <stdio.h>
#define MAXLINE 1000
void reverse(char o[], char l[]);
int mgetline(char line[]);
int main(void){
int len;
char line[MAXLINE];
char rev[MAXLINE];
while((len = mgetline(line)) > 0){
reverse(rev, line);
printf("%s\n",rev);
}
return 0;
}
int mgetline(char s[])
{
int c,i;
for(i = 0; ((c=getchar())!=EOF) && (c!='\n'); ++i)
s[i] = c;
if (c == '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
void reverse(char revi[], char liner[])
{
int i, c, j;
for(i=0;liner[i]!='\0';++i)
;
--i;
if(liner[i]=='\n')
--i;
for(j=0; j<=i ; ++j){
c = i - j;
revi[j] = liner[c];
}
--j;
}
Since you not terminating the revi string at the end, therefore it will print the leftout characters from the previous result if the new input is smaller. Fix it by adding this
revi[j] = '\0';
at the end of the reverse function and delete that last --j;.
The function reverse does not build a string that is it does not append the terminating zero '\0' to the result string.
The second parameter of the function should have the qualifier const because it is not changed in the function.
As all standard C string functions this function should return pointer to the result string.
And it is better to name the function like reverse_copy instead of reverse because the name reverse is usually used when a container is reversed "in place".
It can look the following way
char * reverse_copy( char revi[], const char liner[] )
{
size_t n = 0;
while ( liner[n] ) ++n;
if ( n != 0 && liner[n-1] == '\n' ) --n;
size_t i = 0;
while ( n != 0 ) revi[i++] = liner[--n];
revi[i] = '\0';
return revi;
}

I've written a code for reverse a string. But in output it is generating some garbage. Why?

Here is my code. For word with more than 3 alphabets in o/p garbage values are generated.
#include<stdio.h>
#include<stdlib.h>
int main(){
char a[50],b[50];
gets(a);
puts(a);
int len,i,j;
i=0;
while(a[i]!='\0'){
i++;
}
printf("Length: %d",i);
//reverse
len = i;
j=len-1;
for(i=0;i<=len-1;i++){
printf("\ni=%d j=%d",i,j);
b[i]=a[j];
j--;
}
printf("\n___REVERSED TEXT___\n");
puts(b);
}
For starters neither declaration from the header <stdlib.h> is used in the program. So this directive
#include<stdlib.h>
may be removed.
According to the C Standard the function main without parameters shall be declared like
int main( void )
The function gets is unsafe and is not supported any more by the C Standard. Instead use function fgets.
When the string stored in the array a is being copied in the array b the terminating zero also should be copied to the end of the resulted string.
The program can look the following way
#include <stdio.h>
#define N 50
int main( void )
{
char a[N], b[N];
fgets( a, sizeof( a ), stdin );
size_t length = 0;
while ( a[length] != '\0' && a[length] != '\n' ) ++length;
a[length] = '\0';
puts( a );
size_t i = 0;
for ( ; i < length; i++ ) b[i] = a[length - i - 1];
b[i] = '\0';
printf("\n___REVERSED TEXT___\n");
puts( b );
return 0;
}
Its output might look like
Hello, World!
Hello, World!
___REVERSED TEXT___
!dlroW ,olleH
#include<stdio.h>
#include<string.h>
int main(void){
char a[50],b[50];
printf("\nWhat is the word?");
scanf("%s", a); fflush(stdin);
int j;
printf("Length: %lu",strlen(a));
for(j = strlen(a) - 1; j >= 0; j--){
b[strlen(a) - 1 - j] = a[j];
}
printf("\n___REVERSED TEXT___\n");
printf("\n%s", b);
}
use function strlen of string.h to get the size of the string;
the for goes from the end to the beginning of string a filling the string b

Delete space error in C programming

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#pragma warning(disable:4996)
#define SIZE 100
int main(void){
char str[SIZE];
char str2[SIZE];
int i;
int len;
gets(str);
len = strlen(str);
for (i = 0; str[i] != NULL; i++) {
if (str[i] != ' '){
str2[i] = str[i];
}
}
for (i = 0; i < len; i++){
printf("%c", str2[i]);
}
return 0;
}
It returns the following error:
What is the problem?
I just want to copy some elements in str to str2 without spaces, but when I run, it has got some weird letters.
You need two index variables
one to go through str
one to tell where to write next to str2
code:
len = strlen(str);
int j;
for (i=0, j=0 ; str[i] != '\0' ; i++) {
if (str[i] != ' '){
str2[j++] = str[i]; // store to str2 and increment j
}
}
Then store a final \0 to str2 at index j
str2[j] = '\0';
Finally, to print the result, you can do that one shot
printf("%s\n", str2);
instead of printing one char at a time.
For starters these headers
#include <stdlib.h>
#include <windows.h>
can be removed because neither declaration from the headers is used in the program.
The function gets is unsafe and is not supported by the C Standard any more. Instead use standard C function fgets.
When str is copied in str2 you have to use separate index to access characters in str2 because some characters from str are not copied. Otherwise the array str2 will contain gaps. As result you can not use the previous value of the variable len with the array str2.
Also it is desirable not to copy any other white space characters.
The program can look the following way
#include <stdio.h>
#include <ctype.h>
#define SIZE 100
int main(void)
{
char str[SIZE];
char str2[SIZE];
fgets( str, sizeof( str ), stdin );
const char *p = str;
char *p2 = str2;
do
{
if ( !isspace( ( unsigned char )*p ) )
{
*p2++ = *p;
}
} while ( *p++ );
for ( p2 = str2; *p2; ++p2 )
{
printf( "%c", *p2 );
}
return 0;
}
Its output might be
Hello World
HelloWorld
If you do not study yet pointers then the program can look like
#include <stdio.h>
#include <ctype.h>
#define SIZE 100
int main(void)
{
char str[SIZE];
char str2[SIZE];
fgets( str, sizeof( str ), stdin );
size_t i = 0, j = 0;
do
{
if ( !isspace( ( unsigned char )str[i] ) )
{
str2[j++] = str[i];
}
} while ( str[i++] );
for ( j = 0; str2[j]; ++j )
{
printf( "%c", str2[j] );
}
return 0;
}

copying int to a string

I'am trying to learn c and therefore solving this exercise. My problem is in the part where I have to abbreviate a word. I am using sprintf to convert the integer to a string and write it into my old string. But however I try to achieve it, the last character of the string always gets lost. Why does this happen? Here is the code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
void abreviation(char *arr,int length){
if ( length+1 > 10){
char c = arr[length];
sprintf(arr+1, "%d%c", length-1,c);
}
}
int main() {
int n,i,j;
scanf("%d\n",&n);
char **arr = malloc(n*sizeof(char*));
for(i=0; i < n ; i++){
arr[i] = malloc(sizeof(char)*100);
char c;
for ( j=0; (c = getchar()) != '\n' ; j++)
arr[i][j]=c;
arr[i][j+1]='\0';
abreviation(arr[i],j);
}
for(i=0; i < n; i++)
printf("%s\n", arr[i]);
}
I appreciate any help.
The loop you wrote to input the words stop at '\0', at that point j is indexed to '\0', and then in the abreviation function char c = arr[length c will always be \0 and not the last char in the word (arr).
A simple fix is to change
abreviation(arr[i],j);
to
abreviation(arr[i],j-1);

Resources