Basic C Array function - c

I am new here and programming. I need to write a function to be able to divide a sentence through the desired input and output them separately.
Such as the input is "Hello, How are you..." it's 23 characters and the other input is numerical "6".
Thus, I want to print it as "Hello," and "How are you..."
I think it would be best to use arrays... However, I cannot write the function. I hope someone could help me..
By the way, if I wanted place the function in a header file, how can I manage that.
Thanks a lot...

First the header file that declares the split_string function. (As you are new to programming, I put detailed comments):
/* Always begin a header file with the "Include guard" so that
multiple inclusions of the same header file by different source files
will not cause "duplicate definition" errors at compile time. */
#ifndef _SPLIT_STRING_H_
#define _SPLIT_STRING_H_
/* Prints the string `s` on two lines by inserting the newline at `split_at`.
void split_string (const char* s, int split_at);
#endif
The following C file makes use of split_string:
// test.c
#include <stdio.h>
#include <string.h> /* for strlen */
#include <stdlib.h> /* for atoi */
#include "split_string.h"
int main (int argc, char** argv)
{
/* Pass the first and second commandline arguments to
split_string. Note that the second argument is converted to an
int by passing it to atoi. */
split_string (argv[1], atoi (argv[2]));
return 0;
}
void split_string (const char* s, int split_at)
{
size_t i;
int j = 0;
size_t len = strlen (s);
for (i = 0; i < len; ++i)
{
/* If j has reached split_at, print a newline, i.e split the string.
Otherwise increment j, only if it is >= 0. Thus we can make sure
that the newline printed only once by setting j to -1. */
if (j >= split_at)
{
printf ("\n");
j = -1;
}
else
{
if (j >= 0)
++j;
}
printf ("%c", s[i]);
}
}
You can compile and run the program as (assuming you are using the GNU C Compiler):
$ gcc -o test test.c
$ ./test "hello world" 5
hello
world

First of all string in C is a char * which is an array of char already:
char *msg = "Hello, World!";
int i;
for(i=0; i<strlen(msg); ++i)
{
char c = msg[i];
// Do something
}
If you want to put your function in the header file just define it as inline

Related

Get output line by line from another function (another source file)?

I have two source files: counter.c and main.c:
counter.c:
#include <stdio.h>
int counter(void) {
for(int i = 0; i < 5; i++)
printf("%d\n", i);
return 0;
}
main.c:
#include <stdio.h>
int counter(void);
int main(void) {
char *line;
counter();
return 0;
}
What I want to do is to have each line that counter() prints to be assigned to the line variable so I can do printf("%s\n", line) myself in main.c.
(edit) Unfortunately, this example doesn't translate well to my actual code so maybe I'll just put it here:
https://github.com/venetwork/venet/blob/master/venet-show.c
What I need is to access the result of running this code on a line by line basis in a different source file (GTK3 GUI). The main function for my combined code will be in this file so main() in venet-show.c should be changed to, say, show(). As of this moment I just use an IO Channel (https://developer.gnome.org/glib/stable/glib-IO-Channels.html) to "stream" the output of venet-show.c to the GUI but I want to get ride of it. Any ideas?
So we pass an allocated memory address and not a pointer like you had to the function. This has storage for the result. Use the return snprintf to advance the pointer so not to overwrite previous results.
#include <stdio.h>
int counter(char *answer, size_t array_len) {
for(int i = 0; i < 5; i++)
{
size_t chars_printed = snprintf(answer, array_len, "%d\n", i);
answer+=chars_printed;
array_len-=chars_printed;
}
return 0;
}
int main(void) {
char line[10000];
counter(line, sizeof(line));
printf("%s", line);
return 0;
}

Segmentation fault using strcmp and char *arr[]

I am working on creating a shell and I haven't use C for a while. I have the shell initizing properly but when I try to compare the user input to an array of strings I have I get a segmentation fault. I was planning on adding casce statements in a the for loop to initiate each of the processes once they are called by the user. I haven't included those since I have been trying to figure out how to get the user input to match with a value in my string array. Under debug I was only receiving the first character of the builtins[j] value which kind of makes since since it is a pointer right. However I am stuck and could use some ideas for why this isn't returning 0 when I input "exit". Thanks
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
//This code is for creating a basic shell
void init_shell(int num, char *prompt[]){
char s1[] = "-p";
int result;
if(num>1){
result = strcmp(s1, prompt[1]);
if(result==0){
printf("%s>$", prompt[2]);
}else{
printf("308sh>$");
}
}
//printf("%s\n %s\n %s\n %d\n", prompt[0], prompt[1], prompt[2], result);
else{
printf("308sh>$");
}
}
//The infinite loop for accepting user input until it closes
int main(int argc, char *argv[]){
const char *builtins[7];
builtins[0] = "exit\n";
builtins[1] = "pid\n";
builtins[2] = "ppid\n";
builtins[3] = "cd\n";
builtins[4] = "pwd\n";
builtins[5] = "set\n";
builtins[6] = "get\n";
char usr_in[]="";
char cmp[]="";
while(1==1){
init_shell(argc, argv);//intial prompt for the shell
fgets(usr_in,100,stdin);
//Check for builtin Commands
int cmds_size = 7;
int j=0;
int res;
for(j; j<cmds_size; j++){
res=strcmp(usr_in, hold);
if(res==0){
printf("Execucting\n");
}
else{
printf("no command\n");
}
}
}
return(0);
}
The issue here is that you're writing the user's input to a buffer that isn't big enough to hold anything other than a null terminator.
char user_in[] = "";
The above line tells the C compiler that you need just enough space to store [ '\0' ], which is a single byte. The C compiler doesn't know that you may later write a 100-byte string to that buffer.
When you write to the buffer, the user's input overflows and will overwrite other values in your stack. Since the other values in your stack are pointers, what'll happen is you'll run into seg-faults, since you're writing character values into those bytes, but interpreting them as char pointers.
You are correctly limiting the size of the allowed input from the user to 100 characters, but you should make sure that your buffer is big enough to hold the value you're reading in:
char user_in[101];
for(int i = 0; i < sizeof(user_in) / sizeof(user_in[0]); i++) {
user_in[i] = 0; // Since this is allocated on the stack *in main*, this
// shouldn't be necessary
}
Here's one example of how you can rewrite your main method:
#include <stdio.h>
#include <string.h>
typedef enum { false, true } bool; // If you don't have this
// defined already
int main(int argc, char *argv[]) {
const char *builtins[7];
builtins[0] = "exit\n";
builtins[1] = "pid\n";
builtins[2] = "ppid\n";
builtins[3] = "cd\n";
builtins[4] = "pwd\n";
builtins[5] = "set\n";
builtins[6] = "get\n";
char user_in[101];
for(int i = 0; i < sizeof(user_in) / sizeof(user_in[0]); i++) {
user_in[i] = 0;
}
while(1) {
printf("Enter a command: ");
fgets(user_in, 100, stdin);
bool found = false;
for(int i = 0; i < sizeof(builtins) / sizeof(builtins[0]); i++) {
if (!strcmp(user_in, builtins[i])) {
printf("Found command %s", builtins[i]);
found = true;
break;
}
}
if (!found) {
printf("Didn't find command\n");
}
}
return 0;
}
Also, regarding your function init_shell: you're checking to see if argc is greater than 1, but that only guarantees that argv[1] is defined; it doesn't guarantee that argv[2] is defined. (Remember, argc is the size of the argv array, where the first element is the name of the program being executed). You want to make sure that argc is at least 3 before checking for the prompt flag in the way you are.
It may be overkill for your use-case, but consider using the getopt function for getting a custom prompt value from the user. See http://man7.org/linux/man-pages/man3/getopt.3.html for documentation regarding that method.

Why isn't isalpha working?

I'm working with C and I need to check that the user inputed second command line argument argv[1] is made up of only alphabetical charchaters and if not, to do what is inside the else loop. I used the is alpha function but when i compile and run the program no matter what my second command line argument is (alphabetical or otherwise), its always executing the "else loop". How do i fix this?
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
int a = argc;
if (a != 2)
{
return 1;
}
string b = argv [1];
int c = strlen(b);
string m;
for (int i = 0; i < c; i++)
{
if (isalpha(b[c]))
{
m = GetString();
}
else
{
printf("Please provide a valid keyword\n");
return 1;
}
}
}
Try replacing
if (isalpha(b[c]))
with
if (isalpha(b[i]))
Currently you are checking the element at the index which is the result of strlen(b) at every iteration of your loop. Because array indices are zero based in C b[strlen(b)] is referencing '\0', the null terminator.
In reference to the Keith Thompson comment below and the answer to this question you should actually be casting the value passed to isalpha to an unsigned char to ensure that undefined behaviour is not invoked.
Thus you should change your code to
if (isalpha((unsigned char)b[i]))
to ensure there is no UB
Use isalpha(b[i]) instead of isalpha(b[c])
like this:
if (isalpha(b[i]))
{
m = GetString();
}

Iterating over C string not working

First, my objective with this code: take in a sentence into a C string. Iterate through the sentence and see how many instances of a particular letter occur.
This code is working somewhat but not giving the right number? Not sure why:
#include <stdio.h>
#include <string.h>
int tracker=0;
int letterCount (char *sentence)
{
int s=strlen(sentence);
int i=0;
for (i=0; i<s; i++){
if (sentence[i]=='h') {
tracker++;
}
}
return tracker;
}
int main(int argc, const char * argv[])
{
char *string="Hi there, what's going on? How's it going?";
letterCount(string);
printf("this sentensce has %i H's", tracker);
return 0;
}
The output I'm getting:
this sentensce has 2 H's
Not quite right. Any ideas?
This is the correct code if you mean case insensitive H:
#include <stdio.h>
#include <string.h>
int tracker=0;
int letterCount (char *sentence)
{
int s=strlen(sentence);
int i=0;
for (i=0; i<s; i++){
if (sentence[i]=='h' || sentence[i]=='H') { //'h' is not the same as 'H'
tracker++;
}
}
return tracker;
}
int main(int argc, const char * argv[])
{
char *string="Hi there, what's going on? How's it going?";
letterCount(string);
printf("this sentensce has %i H's", tracker);
return 0;
}
You have just mispelled small and the capital letter in your code.
Remember, the C language is case sensitive!
Although your label talks about the number of Hs, your letterCount looks for hs instead -- and it looks to me like the input you've provided does have two instances of lower-case h, just as it says.
If you want to count them together, you might consider filtering each input with tolower or toupper before checking what you have.
That number looks correct to me: you have 2 'h' characters in that sentence. If you want to count the 'H' characters as well, then you need a separate check.
size_t letterCount(const char* sentence, char c)
{
size_t count = 0;
while(sentence)
{
count += (*sentence == c);
++sentence;
}
return count;
}
What do we see here?
You can't have negative count, so use an unsigned type like size_t
sentence shouldn't be modified, so it should be const
pass in the char you want to match
sentence is a pointer, if it is null you are done. Don't need to call strlen.
sentence is a pointer, the actual pointer is pass by value, so you can modify it (see the increment, no need to make an extra variable)
boolean operators return 1 or 0, so no need to use the if. (Although, I haven't looked at the assembly to see if an if branch or an add 0 is cheaper. YMMV)

strings handling C linux and windows

I'm a newbie in C programming.
I have this issue that I don't understand. It seems that strings under windows are treated in a completely different way respect to linux, why?
Thant's my code
#include <stdio.h>
#include <string.h> // compare strings
void addextname(char *str1, char *str2, char *nome1){
int i,j;
i = 0;
while (str1[i]!='.') {
nome1[i] = str1[i];
i++;
}
j = 0;
while (str2[j]!='\0') {
nome1[i] = str2[j];
i++;
j++;
}
}
int main()
{
char str1[9]="file.stl";
char str2[9]="name.stl";
int len1 = strlen(str1);
int len2 = strlen(str2);
char nome1[len1+len2+1];
addextname(str1,str2,nome1);
printf("%s %s %s\n",str1,str2,nome1);
return 0;
}
My purpose is to read an input filename within its extension (.stl) and add some chars to it keeping that extension. Under linux I have no problem, under windows instead the output filenames are saved unproperly.
My compiling line is
gcc modstr.c -std=c99 -o strings
I really appreciate an answer to that!
You're not 0-terminating nome1. Try:
nome1[i] = 0; /* After the second while. */
Your have created the array nome1 but have not furnished it with anything. Is it psychic?

Resources