Number of elements of command line arguments - c++

I have a problem with command-line arguments.
I need to write a program that will count the size of elements of each command-line argument passed in argv array.
Simple code looks like this.
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 0;
for (i = 0; i < argc; i++)
{
printf("%lu\n", sizeof(argv[i]));
}
return 0;
}
I understand that it is wrong and that "argv" is an array of pointers to a string. I also tried to add asterisk but it brought back "1" (byte) as a result because I said "go to that address" and it showed me the size of the first element of each command-line argument.
So, how can I solve this problem without many and many loops, just with "sizeof" function?
UPD: Sorry for that "%s" mistake. In the actual code I didn't write it.
And I DO understand that sizeof() won't bring me the size of array. I was pointing to the combination "sizeof() / sizeof (char)"
Also, thank you very much for "strlen" reminder. I am studying now. I don't know C language yet. Sorry, for my stupid mistakes.

You are printing the size of a character pointer. Instead you want the length of the string. You can use the standard function strlen :
( note: argv[0] is the program name itself, so 1st number indicates the length of program name.)
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i = 0;
for (i = 0; i < argc; i++)
{
printf("%zu\n", strlen(argv[i]));
}
return 0;
}

Instead of sizeof use strlen() that returns the size of a string while excluding the string termination character from the counting. More information here: Strlen

As it is seen from your program more preciseky from the declaration of the main arguments have type char *. That is they are pointers to first characters of strings that are passed to the program like arguments.
So you need to use standard C function strlen declared in header <string.h> to determine the size of the string passed like an argumnet.
Take into account that the last pointer in the array argv has value NULL.
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
for ( char **p = argv; *p; ++p )
{
printf( "%zu\n", strlen( *p ) );
}
return 0;
}

Related

Array of char arrays C++

I am writing an exchange program and I have a char array that holds another 6 char arrays. The program works fine except for one thing: when I try to print the arrays' values, it prints only the first letter.
Maybe the code isn't right, but I didn't find another way to make this exchange. Actually I think the problem is in pointers that point to that arrays, but again I am not sure.
Here is the code:
#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>
using namespace std;
int main(int argc, char* argv[])
{
cout<<"EXCHANGE POKEMON:"<<endl;
char a[100]="PIKACHU", b[100]="CHARMELEON", c[100]="GEODUDE", d[100]="GYARADOS", e[100]="BUTTERFREE", f[100]="MANKEY", tmp[100];
char t[6] = {*a,*b,*c,*d,*e,*f};
while(1)
{
for(int i = 0; i < 6; i++)
{
cout << i << ") " << t[i] <<endl;
}
cout<<endl<<"Choose a pokemon:";
int x, y;
cin>>x;
if(x == -1)
{
exit(0);
}
cout << "Choose a pokemon to exchange with:";
cin>>y;
*tmp = t[x];
t[x] = t[y];
t[y] = *tmp;
}
}
With this line:
char t[6];
you are not creating an array of arrays of char. You are creating a simple array of chars. So it is no surprise that every element is a single character.
You probably want:
char *t[6] = {a, b, c, d, e, f};
Note that the *a is actually equivalent to a[0]!
Then the tmp array is used wrong: in C you copy strings with strcpy(), not with the assignment operator. Or alternatively you hold a pointer to the original string.
But you are using C++, so why not just use std::string? Maybe you are just learning arrays and want to do it the hard way?
You defined t as an array of char, initialized dereferencing the address of the arrays defined before. That is equivalent to obtaining their first element.
*a is equivalent to a[0]
What you are looking for is an array of char pointer instead:
char *t[6] = {a,b,c,d,e,f};

how to read input files taken as parameters in C++

I've just practiced coding C++. I knew in Java, we could have a public main method, which could read input file names as parameters of the string array argument. But I wonder how I do the same task in C++?
Both Java and C++ follow the same C-like syntax. So it doesn't really differ from what you had in Java. In Java you had a string class :
class Test {
public static void main(String args[]) {
for(int i = 0; i < args.length; i++)
System.out.println("Argument " + i + " = " + args[i]);
}
}
C/C++ mostly use primitive character arrays in order to store strings. Although Standard Template Library also provides string classes, but C++ uses native char arrays to store commandline arguments. The main function takes two variables :
int argc : number of commandline arguments
char *argv[] : an array of character strings
You can also say it can be written as char **argv, because of the underlying representation of two dimensional arrays in C/C++, but both mean the same thing. The equivalent of the above code in C++ would be:
#include <iostream>
int main(int argc, char *argv[]) {
for(int i = 0; i < argc; i++)
std::cout << "Argument " << i << " = "
<< argv[i] << std::endl;
return 0;
}
You do it the same way, with slightly different syntax because C arrays do not store their length, so it is passed as a separate parameter.
int main(int argc, char** argv) {
// Read args from argv, up to argc args.
// argv[0] is the name of the program
// argv[1] is the first argument
}
The main function gives you the argument count and the actual arguments as an array of character arrays.
To safely work with this, you should first turn this information into a std::vector<std::string>.
#include <string>
#include <vector>
int main(int argc, char *argv[]) {
std::vector<std::string> arguments;
for (int index = 0; index < argc; ++index) {
arguments.push_back(argv[index]);
}
}
You will notice that arguments[0] is equal to the filename of the executable (in theory, this depends on the system you're using). If you are on Windows and have an executable called stackoverflow.exe, then starting it with
stackoverflow.exe one two
would result in arguments containing { "stackoverflow.exe", "one", "two" }.

Unable to return string properly in C++ for some range [duplicate]

This question already has answers here:
Returning string from C function
(8 answers)
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
I've made one C++ program using pointers and functions to return the reverse of a string. When the range char p[] in the function rev is low like 25 (less than. 145), the output is like ►↕☻ ☺♠♥, it doesn't reverse, when the range is higher than 145, it works fine in gcc, for Borland TurboC, the minimum range must be 65 otherwise the program prints strange values instead of reversing it.
#include<iostream>
#include<conio.h>
#include<string.h>
#include<stdio.h>
using namespace std;
int main()
{
char str[20];
int l;
char* p1;
//clrscr();
gets(str);
l=strlen(str);
char* rev(char*,int);
p1=rev(str,l);
puts(p1);
return 0;
//getch();
}
char * rev(char* a,int l1)
{
char p[25]; // HERE: higher than 146 is working
int c=0;
for(l1=l1-1;l1>=0;l1--)
{
p[c]=a[l1];
c++;
}
p[c]=NULL;
return(p);
}
In function rev array char p[25]; is a local object of the function. After exiting the function it will not be alive and in general can be destroyed, that is the memory occupied by it can be overwritten by other object or function.
So the returned pointer to the first character of this array is invalid and the program has undefined behaviour.
It is unclear why the array in the function is defined with the size equal to magic number 25. If the second argument passed to the function will be greater than 25 then again there will be a problem because the memory will be overwritten beyond the array.
Also the design of the function is not good. Either the function reverses a string "in place" or copy in the reverse order the sourse array in the destination array and in this case the destination array has to be a function parameter.
And it is a bad idea to use C IO functions in C++ program. Moreover function gets is unsafe and is not supported any more by the C Standard.
The function can look the following way
#include <iostream>
#include <cstring>
char * reverse_copy( char *s1, const char *s2 )
{
size_t n = std::strlen( s2 );
size_t i = 0;
for ( ; i < n; i++ ) s1[i] = s2[n - i - 1];
s1[i] = '\0';
return s1;
}
int main()
{
const size_t N = 20;
char str1[N];
char str2[N];
std::cin.getline( str2, N );
std::cout << str2 << std::endl;
std::cout << ::reverse_copy( str1, str2 ) << std::endl;
}
If to enter phrase
Hello, Priyal Kumar
then the program output will be
Hello, Priyal Kumar
ramuK layirP ,olleH
When you declare
char p[25]
in function rev is only declared locally. When you'll reach the end of function, all of the local variables will be deleted (including array p). The easiest way to fix this is to change char p[25] to:
char *p = new char[25]
but beware, this might cause memory leaks if you won't free memory when you won't need it any more. I'd recommend you use std::string or take a look at some built in functions like strrev in string.h.

Converting to uppercase in C++

Let's say you have:
const char * something = "m";
How would one make this uppercase, using toupper (or something else, if applicable)?
I want to use a char * instead of a string (I can use a string, but then I have to use str.c_str()).
So, how can I make char * something = "m"; contain "M"?
I find you choice of C strings disturbing.. but anyway.
You can't change a string literal (char *something). Try an array:
char something[] = "m";
something[0] = toupper(something[0]);
To change an entire string:
char something[] = "hello";
char *p = something;
while (*p) {
*p = toupper(*p);
p++;
}
As explained in the very famous C book - The C Programming Language by Kernighan & Ritchie in section 5.5 Character Pointers and Functions,
char amessage[] = "now is the time"; /* an array */
char *pmessage = "now is the time"; /* a pointer */
`amessage` is an array, just big enough to hold the
sequence of characters and `'\0'` that initializes it.
Individual characters within the array may be changed
but `amessage` will always refer to the same storage.
On the other hand, `pmessage` is a pointer, initialized
to point to a string constant; the pointer may subsequently
be modified to point elsewhere, but the result is undefined
if you try to modify the string contents.
OTOH, in C, to convert to upper case letters, you can use the following program as a reference.
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int i=0;
char str[]="Test String.\n";
char c;
while (str[i]) {
c=str[i];
putchar(toupper(c));
i++;
}
return 0;
}
In C++
#include <iostream>
#include <string>
#include <locale>
using namespace std;
int main ()
{
locale loc;
string str="Test String.\n";
for (size_t i=0; i<str.length(); ++i)
cout << toupper(str[i],loc);
return 0;
}
EDIT: Adding pointer version (as requested by #John) for the C version
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int i=0;
char str[]="Test String.\n";
char *ptr = str;
while (*ptr) {
putchar(toupper(*ptr));
ptr++;
}
return 0;
}
Hope it helps!
You can use the same algorithmic approach that you know for std::string for raw arrays:
char s[] = "hello world";
std::transform(s, s + std::strlen(s), s, static_cast<int(*)(int)>(std::toupper));
You cannot do this for immutable string literals (like const char * s = "hello world;") for obvious reasons, so you won't get around an additional allocation/copy for that.
Update: As Ildjarn says in the comment, it's important to note that string literals are always read-only, even though for historical reasons you are allowed to bind them to a pointer-to-mutable, like char * s = "hello world";. Any decent C++ compiler should slap you in the face if you attempt this, but it is valid C++ -- but any attempt to actually modify any element of s is undefined behaviour.
You can convert C-string to std::string and then use boost::to_upper to change string in place or boost::to_upper_copy to create upper case copy of the string. Here is the code example:
#include <iostream>
#include <boost/algorithm/string/case_conv.hpp>
int main ()
{
char const * s = "Test String.\n";
std::string str(s);
std::cout << boost::to_upper_copy(str).c_str() << std::endl;
return 0;
}
Hope this helps.
You could do:
#include <algorithm>
#include <iterator>
#include <ctype.h>
char test[] = "m";
std::transform(std::begin(test), std::end(test), std::begin(test), ::topper);
This applies the ::toupper function to character of the string. This is the ::toupper function in the global namespace that comes from C. std::toupper has multiple overloads and ::toupper looks more elegant than static_cast<int (*)(int)>(&std::toupper).

c, c++ most basic double quotes

char* a="HELLO WORLD";
IF ADDRESS of 'H' is 0x01 then the printf with %s prints to D but if the same code is written with manual printing routine
while(*a!=NULL) {printf("%c",n[a]);n++;}
this prints a few more characters..
but
printf("%s",a);
prints it perfectly.
while(*a++) printf("%c", *(a-1)); or
for(;*a++;)printf("%c", *(a-1));
although work but i dont want solutions but the process mechanisms..
so the question coming to my mind is
whether printf gets the length of the string from some register(or any memory unit)
or it performs character check.. then prints...
The way you're indexing into the character string is odd. It works for the string, but won't stop because you never change the value of *a. What your program does is try to get the a offset of n, so for the first 11 positions they are the same, but the loop doesn't terminate because *a will always be 'H'. What you'd want the terminating condition to be is n < strlen(a).
However, the more succinct way to write that program would be:
int main(int argc, char **argv) {
char *a = "HELLO WORLD";
while(*a) printf("%c", *a++);
return 0;
}
This works because a is an array of characters and as we're printing out each character (de-referencing the value stored at the position) we also increment to the next position. The string should terminate with a NULL reference, which will cause the loop to terminate sine *a == 0 at the NULL terminator.
did you mean or you have error:
int main() {
int n = 0;
char* a="HELLO WORLD";
while(a[n] != NULL) {printf("%c",a[n]);n++;}
}
explanation about what is wrong:
while(*a!=NULL) printf("%c",n[a]);n++;
a is not modified anywhere, so *a will not change it's value.
Although n[a] is perfectly valid construct in C I strongly recommend not to use it, because it is semantically incorrect. You access array by index, not index by array.
You increment index (n++) but check the pointer to array. You could possibly increment a inself like this: while(*a!=NULL) {printf("%c",*a);a++;}
The corect way to do this is:
#include <iostream>
using namespace std;
int main() {
char *a="HELLO WORLD";
int n = 0;
while(a[n]!=NULL){
cout<<a[n];
n++;
}
cout<<'\n';
return 0;
}
As far as I remember, by default when you created char* a it will be something as {HELLO WORLD\0} in memory ('\0' is how %s know the end of the your string is)..
Not sure if '\0' == null will yield true.. but I doubt it