I am debugging fortran programs using GDB, and I'd like to write a gdb function to pretty print (format print) a 2D array.
The function needs format string like "%.4f" as an argument, but the command set $format="%.4f" is not correct due to Invalid character '"' in expression.
My questions are:
1.How to assign a format string to a variable?
2.Is it possible to judge the type of variable in the function so that it can use the correct format string automatically.
Thank you very much.
Related
Due to some restriction on my assignment, F77 is used.
I am learning to use subroutine but I encounter error when trying to write string out.
PROGRAM test
IMPLICIT NONE
INTEGER a
CHARACTER*20 STR,str1
STR = 'Hello world'
a = 1
WRITE (*,*) a
WRITE (*,10) STR
CALL TEST(str1)
STOP
END
SUBROUTINE test(str2)
CHARACTER*20 str2
str2 = 'testing'
WRITE (*,10) STR2
RETURN
END
When trying to compile this code, it returns that 'Error: missing statement number 10'
Also, I have some other questions:
What does the *20 mean in CHARACTER*20 STR?
Is this the size of the string?
How about 10 in WRITE (*,10) STR? Is this the length of string to be written?
what does (*,*) mean in WRITE (*,*) a
As you can read for example here:
https://www.obliquity.com/computer/fortran/io.html
the second value given to write is an argument for the implicit format keyword, which is the label of a statement within the same program unit, a character expression or array containing the complete format specification, or an asterisk * for list-directed formatting.
Thus if you provide the data directly, you may want to use * there instead.
Otherwise, your program needs to have the label 10 at some line with formatting statement.
And yes, CHARACTER*20 STR means that the variable STR is of length 20, as you can read for instance here: https://www.obliquity.com/computer/fortran/datatype.html
The *20 after CHARACTER specifies the size of the CHARACTER variable (in this case 20 characters). FORTRAN doesn't use null-terminated strings like other languages, instead you have to reserve a specific number of characters. Your actual string can be shorter than the variable, but never longer.
The comma ( , ) in the write statement is used to separate the various arguments. Some versions of FORTRAN allow you to supply 'named' arguments but the default is the first argument is the file code to write to (a '*' implies the standard output). The second argument would be the line number of a FORMAT statement. There can be more arguments, you'd have to look up the specifics for the OPEN statement in your version of FORTRAN.
Some of your WRITE() statements are specifying to use the FORMAT statement found at lable '10'. But your sample doesn't provide any FORMAT statement, so this would be an error.
If you don't want to deal with a FORMAT statement, you can use an asterisk ( * ) as the second argument and then FORTRAN will use a general default format. That is what your first WRITE(,) is doing. It writes to 'stdout' using a general format.
The following piece of code works in C++ when running on Windows:
void* paramsList[MAX_PARAMS_NUM] = { 0 };
...some code to populate paramsList (p.s MAX_PARAMS_NUM is a constant)
vsnprintf((char*)pStr, MAXLEN, (char*)pTempFormat, (va_list)paramsList);
This code works fine on Windows, but i am trying to make it run on Linux and the program crushes because this conversion of paramsList to va_list doesn't work there.
Now the setting of this scenario is that i get a format string from a server that i don't control. The format string ('pTempFormat') is like the one used in printf of unknown number of % in it (maximum is MAX_PARAMS_NUM) and i populate the paramsList accordingly and then i use vsnprintf to create a string from the format string i got and the values populated in paramsList.(those values can be anything from integers, to hex to char * (aka strings) and any combination of them, according to the format string received from the server).
i don't know how many locations paramsList to pass to vsnprintf until i finish populating it according to the format string received from the server. So i need to somehow either pass a variable number of locations from paramsListto vsnprintf or to convert those locations into va_list (which i couldn't figure out how to do from what i read online).
I also considered using a combination of variadic templates and va_list - to somehow pass a variable number of locations from paramsListto a variadic function and to pass them on to vsnprintf. But i couldn't figure out how to pass certain locations from a given array to a variadic function either.
Update:
I use Visual Studio 2015 to compile on Windows, and GCC 4.9 on Ubuntu.
The error i am getting when trying to compile this code on Linux is: error: ISO C++ forbids casting to an array type 'va_list {aka __va_list_tag [1]}'
va_list is an unspecified type. That means it may be a void* [] or something else entirely.
That it worked by chance in some cases is just that va_list is compatible with void* [] on one particular platform for one compiler, it is by no means indication that this is legal.
The correct way to deal with this is, unfortunately, to stop using the printf family and parse the format string yourself, there is no standard functionality to reach in and fetch the parsed format string to use for yourself.
In converting some FORTRAN code to be compatible with the GNU Fortran compiler, I need to get rid of some of the variable formatting angle brackets (<>) and replace them with equivalent GNU accepted formatting.
The problem is, I'd like to do this while still using the FORMAT statement. The reason for this is that the format statements are very complex, multi-line statements with strings and so forth, so to determine the size of the string buffer necessary for a very large code with multiple instances of variable formatting is undesirable.
That is, I could replace
write(10,100)blah,blah...,blah
100 format(... <ii>i10, 'this and that ',
.../
...)
with
vfmt=''
write(vfmt,'(a,...,a)')'(',...,ii,'i10','this and that ',...,')'
write(10,vfmt)blah,blah...,blah
where vfmt is some very long string buffer, but I'd rather do this only as a last resort.
Is it possible to make the FORMAT statement partially variable? Something like
vfmt=''
write(vfmt,'(i0)')ii
write(10,100)blah,blah...,blah
100 format(..., vfmt//'i10',...)
I know from attempting this that this specific approach does not work.
Thanks.
I am trying to learn c++, and for an assignment I have ran into a problem. I am trying to get an integer value from a string that a user enters all on one line.
Ex.) The user inputs: "Change value to 15."
What is the best way of getting the 15 from that string? I have looked around for a while, but could only find if a string was only integers.
Thanks in advance!
Why not use a mixture of getline(grabs your whole line) and string stream(tokenizes the input) and put them all in a vector(easier to use than an array), grab the one at .size()-1 and do an atoi on that. Might be overkill, but string stream could do what you want. For a small tut this could help http://www.dreamincode.net/forums/topic/95826-stringstream-tutorial/
This might not be the best way but to get something done now you can use strtok to tokenize your input string and then examine the tokens for your integer value integer. One of the answers here [link] suggests using strtok to tokenize a string.
If you know the format of you string or know that there will always be a single integer value then you can use string::find_first_of and string::find_last_of [link] and then just get the substring and use string::stoi.
I have a c++ program, I would like the first argument of the main (argv[1]) to correspond to a table of float. Is it possible to do that??
I was thinking about putting in a string my floats separated with spaces (e.g. "1.12 3.23 4.32 1.1 ...")
Is there a way to automatically convert such a string into a table of floats? If I understand well the atof function converts a string into a double. So it seems it could be possible to split my string using the spaces and then convert each portion using atof.
This option does not seem to be very efficient to me? In addition it returns double and not float :(
So, is there a better way to pass table of float as argument of a c++ program ?
Thank you
A stringstream can do both the splitting at spaces and the parsing into a float.
std::stringstream ss(the_string);
std::vector<float> v(std::istream_iterator<float>(ss),
(std::istream_iterator<float>()));
// the extra parentheses here are ugly but necessary :(
How to obtain the string with the data depends on how large it is and where it is supposed to come from. Just keep in mind that in many systems the arguments passed to program are already split by spaces, putting each part in a different element of argv.
Save it in a text file, and then read it from the file when your program starts. I isn't worth it to pass it as a command-line argument.
The main() parameter list is as it is. You can pass the strings of your numbers as arguments to your program. The main function will have to parse its argument.
When you want to pass a space separated list of numbers in argv[1] you can use the strtok function to get the individual number strings and have to pass it to a conversion function.
When your conversion function returns a double you should check that the result can be represented by a float and cast the value to a float variable. But I would consider to use double as the internal representation.
In addition to Singer's answer:
The commandline should be used mainly by human, not computer. If you really need a table of values, use configuration file. You can always use human readable format for it.