Producing uppercase letters without pointers - c

I am trying to write a function, uppercase, that converts all lowercase characters in a string into their uppercase equivalents.
However, I am getting a Bus 10 error in my code. I know that string literals cannot be modified in C; so, I am not sure if this is the right approach.
My code is below:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
int uppercase(char source[])
{
int i;
for(i=0; i<=strlen(source); ++i)
if (source[i]>= 'a' && source[i]<= 'z')
source[i]= source[i]-'a' +'A';
else
source[i]=source[i];
}
int main(){
uppercase("cold");
return 0;
}
Ideally this function should return COLD.I suppose the error lies in my whole if statement.

The reason you get a crash is that your code modifies a string literal. Characters inside string literals are placed in protected memory area, and therefore may not be changed: it us undefined behavior.
Replace this
uppercase("cold");
with this:
char cold[] = "cold";
uppercase(cold);
Now the characters of the string are placed in a modifiable area of memory, allowing you to make changes as needed.

Your absolutly working with pointers without even to know it.
In your function definition
int uppercase(char source[])
char source[] is considered by the compiler as a pointer to char (char *source)
So when passing a string literal to uppercase() your just passing it's adress. Then in your function your trying to modify it which leads to undefined behaviour.
Also you can't return a whole array so you just return a pointer to it.
char *uppercase(char source[])
{
int i;
size_t len = strlen(source);
char *tmp;
tmp = malloc(len+1);
if (tmp!=NULL){
memcpy(tmp, source, len+1);
for(i=0; i<len; ++i){
if (tmp[i]>= 'a' && tmp[i]<= 'z'){
tmp[i]= tmp[i]-'a' +'A';
}
}
}
return tmp;
}
Then:
int main(){
char *str = uppercase("cold");
printf("%s", str);
free(str);
return 0;
}
You complete code: http://ideone.com/BJHDIF

Related

define function with pointer input

I don't fully understand how to work with pointers.
Inside the function is where I need to write code to return the length of input string.
int mystrlen (const char *s)
{
char *s[1000], i;
for(i = 0; s[i] != '\0'; ++i);
printf("Length of string: %d, i");
return 0;
}
Could you tell me how to make it work?
Thank you!!
Remove char *s[1000], declare int i instead of char i, and return i rather than 0:
You need to remove the s inside the function body because it is "shadowing the variable" s that is a function parameter, meaning the s function parameter cannot be read at all.
Changing char i to int i will likely increase the range of possible values to return. If you pass a string with 128 characters in it, char i would result in returning -128 if it is a signed 8-bit type. int is guaranteed to be 16-bit, allowing for strings up to 32767 characters (more than enough for most common uses of a string length function).
You return i because otherwise the function is pointless; even if you print the value, you'd need a way to use the string length, and you can't do that if you don't return it from the function.
Corrected code with example:
#include <stdio.h>
int mystrlen(const char *s)
{
int i;
for (i = 0; s[i] != '\0'; ++i);
return i;
}
int main(void)
{
const char *s = "Hello world!";
int len = mystrlen(s);
printf("Length of string: %d\n", len);
return 0;
}
First of all, using pointers, as the number says, consist in using a reference instead of the actual variable, so if you pass a reference by parameter, you are not passing the actual value of it, just an address to it!
The correct code is:
#include <stdio.h>
int mystrlen (const char *s)
{
int i;
for( i = 0; s[i] != '\0'; ++i);
printf("Length of string: %d\n", i);
return 0;
}
void main(){
char *string = "Hello World";
mystrlen(string);
}
Another thing to point out is that you're trying to declare a const variable and change it. When you declare a const variable it should not change.

Print ABC - string [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
My program need to print all the ABC but I see I have problems with the code. How I can fix it? (no pointer for this time).
What is the runtime error in the code and how to fix it?
Here is the code:
// Elvis’s hip and happening ABC-printing code
#include <stdio.h>
#include <string.h>
#define NUM_ABC_LET 26
void makeABC(char abc[NUM_ABC_LET]);
int main() {
char abcString[NUM_ABC_LET] = "";
makeABC(abcString);
puts(abcString);
return (0);
}
void makeABC(char abc[NUM_ABC_LET]) {
char letter;
for (letter = 'a'; letter <= 'z'; letter++) {
strcat(abc, letter);
}
}
The problem is that the strcat function expects both arguments to be (zero-terminated) strings. You only pass one string, and then one single character as arguments (which should give you compiler warnings).
You need to convert this single characters into a string (or an array) of a single character.
And don't forget that strings in C are zero-terminated.
What happens you use the single character as argument to the strcat function is that the compiler converts it to an int which is then in turn converted to a pointer. The problem with this is that the address 'a' (for example) is not a valid address to a string. That will lead to undefined behavior and a crash.
Your program logic is correct, the problem is the calling of the strcat() function. The strcat() function is implemented as:
char *strcat(char *dest, const char *src)
{
char *ret = dest;
while (*dest)
dest++;
while (*dest++ = *src++);
return ret;
}
The second argument must be a string instead which you pass a character.
This is the reason for your run time error.
Can you try something like following? I haven't tested the following but it should work on most part.
// Elvis’s hip and happening ABC-printing code
#include <stdio.h>
#include <string.h>
#define NUM_ABC_LET 26
void makeABC(char abc[NUM_ABC_LET]);
int main()
{
char abcString[NUM_ABC_LET + 1];
makeABC(abcString);
puts(abcString);
return 0;
}
void makeABC(char abc[NUM_ABC_LET + 1])
{
char letter;
int i=0;
for(letter = 'a'; letter <= 'z'; letter++)
{
abc[i] = letter;
i++;
}
abc[i]='\0';
}
Your program has several issues:
You cannot call strcat with a char, you must pass char * arguments, pointing to null terminated C strings.
The array into which you compose the alphabet is too short: you need to define it with a size one larger than the number of characters for the final '\0' terminator.
Here is a corrected version:
#include <stdio.h>
#include <string.h>
#define NUM_ABC_LET ('z' - 'a' + 1) // 26 ASCII letters
void makeABC(char *abc); // makeABC receives a pointer to an array of char
// this declaration is equivalent to
// void makeABC(char abc[NUM_ABC_LET+1]);
// but less error prone
int main(void) {
char abcString[NUM_ABC_LET + 1] = "";
makeABC(abcString);
puts(abcString);
return 0;
}
void makeABC(char *abc) {
char letter;
char buf[2]; // a buffer for a 1 letter C string
for (letter = 'a'; letter <= 'z'; letter++) {
buf[0] = letter; // make a 1 letter string
buf[1] = '\0'; // set the null terminator
strcat(abc, buf);
}
}
Prototype of strcat is
char *strcat(char *destination, const char *source);
means our source as well as destinations should and must be string so this is the issue that why if you compile in turbo c it will through error of
"type mismatch".
and if you wanna write program for printing ABC up to Z than simply write
void main()
{
int i;
for(i = 65; i<=90; i++)
{
printf("%c", i);
}
}
I hope you will like it......
As a slight variation, I would suggest passing the length of the character array to the function, so that the function does not overflow the array.
As the character array is passed to the function as a pointer, the function does not know it's size.
In your case you know the size, but for the future it might be better to explicitly pass the size.
Also I just copied the characters rather than use strcat, and added the null termination at the end.
#include <stdio.h>
#define NUM_ABC_LET 26
/* function takes pointer to array and size of array */
void makeABC(char *abc, int len);
int main()
{
/* array needs to include space for null termination */
char abcString[NUM_ABC_LET + 1];
/* call function with pointer + size */
makeABC(abcString, NUM_ABC_LET);
printf("%s\n", abcString);
return (0);
}
void makeABC(char *abc, int len)
{
int n;
for(n = 0; n < len; n++ ) {
/* add letters to the array */
abc[n] = n + 'a';
}
/* put a null termination on the end */
abc[n] = '\0';
}

C: reverse string function not affecting pointer

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int reverse(char *, int);
main()
{
char *word = "Thanks for your help";
reverse(word, strlen(word));
printf("%s", word);
getchar();
}
int reverse(char *line, int len)
{
int i, j;
char *newline = malloc(strlen(line));
for (i = len - 1, j = 0 ; i >= 0; i--, j++)
{
newline[j] = line[i];
}
newline[j] = '\0';
line = &newline;
}
Hey folks. I've got a simple C question that I can't seem to solve.
The program above is meant to take in a string and print it out backwards. Reverse is the function by which this is done.
The issue, specifically, is that when I print word in main(), the string appears unchanged. I've attempted to make the address of line the address of newline, but it doesn't have any effect.
int reverse(char *line, int len)
{
int i, j;
char *newline = malloc(strlen(line));
for (i = len - 1, j = 0 ; i >= 0; i--, j++)
{
newline[j] = line[i];
}
newline[j] = '\0';
line = &newline; // Your problem is here
}
You're merely assigning to the local line pointer. This has no effect on the calling function whatsoever.
Consider instead:
char *reverse(char *line, int len)
{
// ...
return newline;
}
Additional advice:
Turn on compiler warnings, and heed them. You've got lots of little things wrong (e.g. reverse isn't currently returning anything, but is declared as returning int).
Given that the first argument of reverse is a pointer to a C string (NUL-terminated), there's no need to take a length argument as well.
A reverse function doesn't necessarily need to be defined as returning a copy of the string, reversed. It could instead reverse a string in-place. Note that you cannot pass a string literal to a function like this, as they are read-only.
Here's how I would write this:
#include <stdio.h>
#include <string.h>
void reverse(char *str)
{
size_t i, j;
for (i = strlen(str) - 1, j = 0 ; i > j; i--, j++)
{
// Swap characters
char c = str[i];
str[i] = str[j];
str[j] = c;
}
}
int main(void)
{
// Mutable string allocated on the stack;
// we cannot just pass a string literal to reverse().
char str[] = "Here is a test string";
reverse(str);
printf("Result: \"%s\"\n", str);
return 0;
}
Note that the for loop condition is i > j, because we want each to only traverse half the array, and not swap each character twice.
Result:
$ ./a.exe
Result: "gnirts tset a si ereH"
Take a look at the code below:
void addOne(int a) {
int newA = a + 1;
a = newA;
}
int main() {
int num = 5;
addOne(num);
printf("%d\n", num);
}
Do you see why that will print 5, and not 6? It's because when you pass num to addOne, you actually make a copy of num. When addOne changes a to newA, it is changing the copy (called a), not the original variable, num. C has pass-by-value semantics.
Your code suffers from the same problem (and a couple other things). When you call reverse, a copy of word is made (not a copy of the string, but a copy of the character pointer, which points to the string). When you change line to point to your new string, newLine, you are not actually changing the passed-in pointer; you are changing the copy of the pointer.
So, how should you implement reverse? It depends: there are a couple options.
reverse could return a newly allocated string containing the original string, reversed. In this case, your function signature would be char *reverse, instead of int reverse.
reverse could modify the original string in place. That is, you never allocate a new string, and simply move the characters of the original string around. This works, in general, but not in your case because char pointers initialized with string literals do not necessarily point to writable memory.
reverse could actually change the passed-in pointer to point at a new string (what you are trying to do in your current code). To do this, you'd have to write a function void reverse(char **pointerToString). Then you could assign *pointerToString = newLine;. But this is not great practice. The original passed-in argument is now inaccessible, and if it was malloc'd, it can't be freed.

Function makes an array empty

I have the following code:
#include <stdio.h>
void insertion_sort(char[], int);
void swap(char*, char*);
int main() {
char s[] = "hello world";
puts(s);
insertion_sort(s, sizeof(s)/sizeof(char));
puts("done\n");
puts(s);
return 0;
}
void swap(char* a, char* b) {
char tmp = *a;
*a = *b;
*b = tmp;
}
void insertion_sort(char s[], int n)
{
int i,j;
/* counters */
for (i=1; i<n; i++) {
j=i;
while ((j>0) && (s[j] < s[j-1])) {
swap(&s[j],&s[j-1]);
j = j-1;
}
printf("%s\n", s);
}
}
The problem is, after the insertion_sort() function call, s becomes empty - puts(s) prints nothing.
Please advise.
Change:
insertion_sort(s, sizeof(s)/sizeof(char));
to:
insertion_sort(s, strlen(s));
otherwise you will be including the '\0' terminator of s[] in your sort.
Note that you will need an additional header for strlen so change:
#include <stdio.h>
to:
#include <stdio.h> // printf etc
#include <string.h> // strlen etc
The problem is that the length that you pass to insertion_sort includes terminating \0 character, which happens to have value 0, so in sort it is placed as the first element of your array. This is why your last puts() prints nothing - because the first character is now "the end of a string".
I suggest you to calculate the size of a string using strlen() which will return the length of a string excluding terminating character. Or if you want to do it your way, take terminating character into consideration and substract it from the total length.

Error with mystrlen function

I was trying to write out some of the implementations of the string functions available in C. My code is:
#include <stdio.h>
#include <stdlib.h>
char *mystrcpy(char *s1, char *s2)
{
while(*s1++ = *s2++);
return s1;
}
int mystrlen(char *s)
{
int len = 0;
while(*s != '\0')
{
len++;
}
return len;
}
int main(void)
{
char arr = "Hi";
char arr1[10];
char arr2[] = "Hello";
int length;
mystrcpy(arr1, arr2);
printf("%s", arr1);
length = mystrlen(arr);
printf("%d", length);
return 0;
}
mystrcpy works fine, but the other method mystrlen does no execute. What could be the error? The following is the program termination note:
Process terminated with status -1073741510 (0 minutes, 4 seconds)
Also, there are few warnings related to casts. Is there any place in the code where I should be using any cast?
First, your mystrlen has an infinite loop.
Fixed code:
int mystrlen(const char *s)
{
int len = 0;
while (*s++ /* increment to next character every loop */ != '\0')
{
len++;
}
return len;
}
Also added const since you never change the data referred to by *s
Second, the assignment: char arr="Hi"; is not valid.
You are attempting to assign a char[] array to a char variable. The correct form would be one of the following:
char arr[]="Hi"; // array syntax
char *arr="Hi"; // pointer syntax
Given your invalid arr assignment, your runtime error is most likely caused by mystrlen attempting to incorrectly deference arr.
What compiler are you using? Most conforming compilers should have caught the second issue. If using GCC, add the -Wall flag to your makefile.
This:
char arr="Hi"; /* Should have caused compiler warning,
as is attempting to assign a char
to a char[3]. */
should be:
char arr[] ="Hi";
or:
char* arr = "Hi";

Resources