/* squeeze: delete all c from s */
void squeeze(char s[], int c)
{
int i, j;
for (i = j = 0; s[i] != '\0'; i++)
if (s[i] != c)
s[j++] = s[i];
s[j] = '\0';
}
int main(void)
{
squeeze("squeeze", 'z');
return 0;
}
I compiled it with gcc and ran it, and got a segmentation fault as a result.
Anything wrong with this example?
thanks to men,i have just made a usual mistake.
Your example shows that you're trying to apply squeeze() to a string literal ("squueze"). This is not correct, since string literals are not always modifiable so it's invalid to try
to modify them. You need to call it with a character array:
#include <stdlib.h>
int main(void)
{
char test[] = "squeeze";
squeeze(test, 'z');
return EXIT_SUCCESS;
}
Related
I am studying "The C Programming Language, 2nd Ed." by Brian Kernighan and Dennis Ritchie. I was on Exercise 1-19 of the book. The question asks to define a function reverse(s) which reverses a character string a. And we have to write a program which reverses it's input one at a time.
//This program is working on online compiler but not here
#include <stdio.h>
void reverse(char s[]);
int main(void) {
int h = 0; // sort of automatic variable just to
// keep storing characters in current line
char s[200];
char c;
for (int i = 0; i < 1000; i++)
s[i] = '\0';
while ((c = getchar()) != EOF) {
if (c != '\n') {
s[h++] = c;
} else {
s[h++] = c;
h = 0;
reverse(s);
for (int i = 0; i < 1000; i++)
s[i] = '\0';
}
}
}
void reverse(char s[]) {
int i = 200;
while(i >= 0)
if(s[i--] != '\0')
putchar(s[i]);
printf("\n");
}
So when I run this code with gcc on my system, I don't get any errors while compiling, but I can't type any input for some reason. However, the program runs correctly when I use an online C compiler.
void reverse(char s[]) {
int i = 200;
while(i >= 0)
if(s[i--] != '\0')
putchar(s[i]);
printf("\n");
}
if you postdecrement your string index, you are first using value at 200 position, which is invalid (it's one position out of the array) so you are doing bad. To do it properly, you need to predecrement it, as in:
void reverse(char s[]) {
int i = 200;
while(i >= 0)
if(s[--i] != '\0')
putchar(s[i]);
printf("\n");
}
but there's still an error... as you pass a null terminated string, you cannot be sure of what there is in the array after the null.... (can be another null?) so you have to search for the null from the beginning of the string (and this is good, because the most of the time you will feed the routine short strings, and now you don't depend on the array size, which you assumed by a constant 200. One good way to do it is with the strlen() function, as in:
void reverse(char s[]) {
int i = strlen(s);
while(i >= 0) /* ??? see below */
if(s[--i] != '\0')
putchar(s[i]);
printf("\n");
}
and then, the test you do is not necessary at all (you already found the leftmost null):
void reverse(char s[]) {
int i = strlen(s);
while(i >= 0) /* still more below VVV */
putchar(s[--i]);
printf("\n");
}
... and there's still a little mistake... you have to stop when i <= 0 and not when i < 0 as you are predecrementing now:
void reverse(char s[]) {
int i = strlen(s);
while(i > 0) /* here!! */
putchar(s[--i]);
printf("\n");
}
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.
As the title says. I don't Understand why this code gives me segfault!
#include <stdio.h>
void cp(char s[], char d[]);
int main () {
char s[100] = "hi there how are you";
char d[100];
cp(s, d);
printf("%s\n++++++++\n%s\n", s, d);
return 0;
}
void cp(char s[], char d[]) {
int i, p = 0;
while (s[i] != '\0') {
d[i] = s[i];
++i;
++p;
}
}
I know the cp implementation is terrible! I wrote it like this just for fun, then the segfault happened.
In this line of code:
int i, p = 0;
you only initialize p, variable i is uninitialized, reading from it leads to UB.
Proper loop could be written like this:
for( size_t i = 0; ( d[i] = s[i] ) != 0; ++i );
(it will also copy null-terminator which you would be missing if initialize i properly)
Another variant is classical C way:
void cp(const char *s, char *d)
{
while( *d++ = *s++ );
}
but usually in C target is the first parameter, not the second (for example strcpy())
You copy only while:
while (s[i] != '\0')
so '\0' isn't copied so when you run:
printf("%s\n++++++++\n%s\n", s, d);
you get a segfault.
Also i is uninitialised:
int i, p = 0;
using separate lines avoids this typo:
int i = 0;
int p = 0;
an uninitialised i can blow up:
d[i] = s[i];
causing a segfault.
I just started trying to learn C a couple days ago by following along with the K&R book. I am not totally new to programming but I would say I am a novice. I've been doing mostly fine so far but I've been having a lot of trouble with array manipulation. In section 2.8 of the book, it defines a function called squeeze which takes in an array of characters and a single character and removes all instances of the single character from the array. I was confused at first because this was a void function.
#include <stdio.h>
void squeeze(char s[], char c);
int main(){
char s[] = "hello";
squeeze(s, 'l');
printf("%s\n", s);
}
void squeeze(char s[], char c){
int i, j;
for (i = j = 0; s[i] != '\0'; i++){
if (s[i] != c)
s[j] = s[i];
++j;
}
s[j] = '\0';
}
I implemented it into my own C program and, when I call the function in Main, it just prints my original array without altering it. I am reasonably sure that this is because I am not changing the array s[] with the Squeeze function before I call printf, but rather changing a copy of the array that isn't being used. I have researched using pointers to refer to arrays in C but I am still very confused on how to do that correctly, because no matter what I try I either get a segment error or the array is not changed. Can anyone help me understand how pointers and arrays work in this context?
EDIT: I did originally state the name of the parameter in the function prototype and declaration, but I made an error in copying it.
I am reasonably sure that this is because I am not changing the array s[] with the Squeeze function
Function prototype is ok:
void squeeze(char [], char c);
It's totally ok to parse array here, because array will decay to pointer anyway in the context of function parameter.
Your implementation wasn't correct, though:
You must provide the name of the parameter s
And must enclose your if statement properly, otherwise ++j; will be executed no matter whether the condition if (s[i] != c) is met or not.
Here's a guide to fix the two issues:
void squeeze(char s[], char c){ // <-- 1) must provide parameter name
int i, j;
for (i = j = 0; s[i] != '\0'; i++){
if (s[i] != c)
{ // <-- 2) must enclose if statement properly
s[j] = s[i];
++j;
}
}
s[j] = '\0';
}
you are changing the array with the squeeze function. But the squeeze function cant produce the output you needed beacause there is an implementation problem with the function.
#include <stdio.h>
void squeeze(char [], char c);
int main(){
char s[] = "hello";
squeeze(s, 'l');
printf("%s\n", s);
}
void squeeze(char s[], char c){
int i, j;
for (i = j = 0; s[i] != '\0'; i++){
if (s[i] != c)
s[j++] = s[i];
}
s[j] = '\0';
}
This one will produce the output you needed. Because in the case of if statement If you not gave any curly brackets The immediate line to the if loop will be taken as in the loop.
So in the case of
if (s[i] != c)
s[j] = s[i];
++j;
The ++j wont taken as in the loop. If you want to add ++j to loop. Then use the following code.
if (s[i] != c){
s[j] = s[i];
++j;
}
All are false in the internet, you should reassign the new variable
void squeeze(char s[],char c) {
printf("s=%s\n",s);
int i, j;
char new_s[20];
for (i = j = 0; s[i] != '\0'; i++)
{
if (s[i] != c)
{
new_s[j] = s[i];
j++; //这里加了一但是 s[j] 没有赋值,下一个循环时才赋值。。
//而最后一次没有下一个循环,所以s[j] 还没有赋值
}
}
printf("s=%s\n",new_s);
}
#include <stdio.h>
#define MAXLINE 10
void reverse(char s[]);
void getline(char b[], int lim);
int main() {
char s[MAXLINE];
getline(s, MAXLINE);
reverse(s);
return 0;
}
void reverse(char s[]) {
int i;
int len = 0;
for (i=0; s[i] != '\0'; i++) {
len = len + 1;
}
char b[len + 1];
for (i = 0; i < len; i++) {
b[(len - 1) - i] = s[i];
b[len] = '\0';
}
printf("%s : %s\n", s, b);
}
void getline(char b[], int lim) {
char c;
int i;
for (i=0; i < lim-1 && (c = getchar())!= EOF && (c!='\n'); ++i) {
b[i] = c;
}
if (c == '\n') {
b[i] = '\n';
}
}
why am i getting an error for the get line unction? It says in Xcode "conflicting types for 'get line'. Also in another error, it says "Too few arguments to function call, expected 3, have 2?
Also can someone explain the order of evaluation for the "condition" part of the for loop? (I'm talking about the &&'s). Thanks a lot!!!
(1)..Your program is correct.But,already one library function getline is exist in library.We know that predefined function's prototype declarations are present in header file.For getline predefined function, declaration is already present in stdio.h...In your program, you are also declared prototype for getline .We know well that It is not possible two declarations for one function.So only you got error.Try to run your program with othername for that function...
(2)..for (i=0; i < lim-1 && (c = getchar())!= EOF && (c!='\n'); ++i)
In for loop you are checking three conditions..you are checking for '\n' also.so,You should give input as string format only.But actually it is not string.You should give characters as input continuously without pressing ENTER.