Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

dougdrums posted:

I didn't think about catch throwing the exception. When I took java my instructor straight out told us he had no clue what it was for. Thanks.

Then the Java you were taught is crippled, because finally is fundamental.

Pseudo-code, since it's been so long since I worked in Java:

code:
File f = new File("somefile", "r");
try
{
  String str = f.read(...);
  // do stuff with str
  return true;  // success!
}
catch (IOException e)
{
  // some problem occurred while reading from f; handle it
  return false;  // failure!
}
finally
{
  // whether you're returning true or false, close the file when you're done
  f.close();
}
The code in finally always gets called, so it's where you put clean-up code that always has to happen no matter whether exceptions are thrown or not.

Without finally, you'd have to write this in one of two ways:

code:
File f = new File("somefile", "r");
try
{
  String str = f.read(...);
  // do stuff with str
  f.close();
  return true;  // success!
}
catch (IOException e)
{
  // some problem occurred while reading from f; handle it
  f.close();  // <-- repeated code, not good!
  return false;  // failure!
}
In this case, it's just one line, but if you had more complicated things to clean up, or lots of different exceptions to catch, repeating the code would be very bad. It's really easy to forget to put "f.close" in the exception handler, which would mean if an exception happens your file stays open forever.

code:
bool result;
File f = new File("somefile", "r");
try
{
  String str = f.read(...);
  result = true;  // success!
}
catch (IOException e)
{
  // some problem occurred while reading from f; handle it
  result = false;  // failure!
}
f.close();
return result;
This is just clumsy and cumbersome, and breaks down as soon as you have more complicated control flow.

Actually, it just occurred to me that neither of these will work if you don't want to catch IOException - if your routine is supposed to throw exceptions to the parent, there's absolutely no way to safely clean up without the finally statement:

code:
File f = new File("somefile", "r");
String str = f.read(...);  // throwing an exception here means f.close is never called
f.close();
C++ doesn't "need" a finally statement because it doesn't have garbage collection, so thing's are guaranteed destroyed as soon as they go out of scope, not "whenever the system decides it needs some more memory". (But sometimes you have to jump through some hoops to make RAII work naturally when a finally statement would be easier - welcome to C++.)

code:
{
  File f("somefile", "r");
  try
  {
    String str = f.read(...);
    result = true;  // success!
  }
  catch (IOException e)
  {
    // some problem occurred while reading from f; handle it
    result = false;  // failure!
  }
  // f goes out of scope and gets destroyed, no matter how the routine exits
  // f's destructor calls close()
}
Someone who doesn't know what finally is for has no business teaching Java.

Adbot
ADBOT LOVES YOU

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
I'd probably write a helper function:

code:
Class loadClass(String classPath)
{
  try
  {
    return Class.forName(classPath);
  }
  catch (ClassNotFoundException e)
  {
    return null;
  }
}

...

Class c = loadClass(someclasspathA);
if (c == null) c = loadClass(someclasspathB);
if (c == null) throw new ExceptionOfDoom();

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

odi3 posted:

How would i do that?
when i debug and print the code before i send and receive, its correct. I assumed that sscan and sprintf were working properly?

Withouth delimiters, how is scanf supposed to know the difference between "44.234" followed by "55.1", and "44.2345" followed by "5.1"?

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
What's wrong with storing a List (or Vector, or whatever Java calls it) as the value for each key of the HashMap?

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

StumblyWumbly posted:

Hey, I'm a hard/firmware guy who only writes in C, Verilog and VHDL.

I need a simple language I can use to write scripts to manipulate text files. About the most complicated thing I'll do is read in a text file, strip out some stuff, and convert the ASCII into hex.

What language or tool would be best for this kind of stuff? It would have to run on a Windows XP system.

Python.

Some will say Perl, but Perl is terrible. Others will say Ruby, which is a better choice, but I think Python will fit your background better.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

MEAT TREAT posted:

I don't it's fair to dismiss a language as terrible without any explanation. In fact you didn't even mention why ruby or python are any better than Perl at text processing which has always been Perl's forte.

It may not be "fair", but it's accurate. Perl is a terrible language, and I would strongly advise everyone to avoid as hard as possible.

Ruby and Python aren't better than Perl at text processing - Ruby is just as good (because it stole all its text handling from Perl, so it's pretty much the same in that respect), and has the advantage of not being terrible in all other respects. Python is slightly more cumbersome, but not enough to be a huge problem, and will be easier to pick up for somebody who only knows C because it doesn't have a lot of new control-flow constructs to learn.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Triple Tech posted:

Uhh, whatever. If you want the job done in a blindingly fast manner with respect to time invested/development speed, go Perl, absolutely.

Ruby is better than Perl for this.

quote:

If these go beyond "one time use" then either 1) learn how to program good, defensive Perl 2) :( choose a different language.

Everything goes beyond a one time use.

Learning to program "good, defensive Perl" is a huge undertaking compared to learning how to program well in any other language. The language structure is just set up to throw everything together and lash it up with whatever's handy. Sure, some people have the discipline to write intricate, well-designed code in Perl, but if you're just starting out so you have nothing invested in Perl, why would you go to the effort?

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
I forgot to mention that one reason I specifically recommended Python was that I know it works extremely well on Windows (I actually prefer the Windows installer from python.org to ActiveState Python, which has add-ons).

I also was in too much of a hurry earlier to say the reason I recommend it to someone who knows C - a lot of the built-in libraries it comes with are organized like common POSIX libraries, so it should be quite familiar to someone who mainly knows C.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

floWenoL posted:

Why don't you try making recommendations without sparking a language debate? Even though your rose-colored (or ruby-colored ha ha) evaluation of Python and Ruby's text processing capabilities as compared to Perl's are amusing.

Because the guy specifically asked for text-processing languages, so I knew somebody very early on would say, "Perl is the no-brainer for this," which it is not.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

nbv4 posted:

and no, using radio buttons instead is not a proper solution.

Bullshit.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
What do you mean "at least"? An instant segfault is the best kind of error to have, because it's immediately obvious that something's wrong and it's easy to find out exactly where the error happened.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
Should work. Are you sure inputString isn't declared "const"? (And this isn't in a const method?)

Googling C3070 turns up a C# error - are you using std::string or some Microsoft string class?

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Moof Strydar posted:

I could probably get as far as drawing some lines in OpenGL, but I don't really know how to proceed from there, or how to make a piano roll that fits in with an existing GUI framework. Are there any references out there on writing custom GUIs/widgets or whatever? Preferably in Python (a long shot, I know)?

Absolutely - both wxPython and PyQT are fantastic GUI frameworks (I prefer PyQT). Google will find you lots of good stuff.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Milde posted:

Have you implemented any applications that bundle either framework? I downloaded wxPython's OS X framework and the disk image is around 33 MB. I don't know what that says about how much space it occupies in frozen form, but it definitely turned me off to messing around with it initially. I'd be curious to see if PyQt is any easier or harder to bundle with a frozen Python application.

No, I've never been responsible for the final packaging.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Kaluza-Klein posted:

I have since discovered that the software will export these lists to a csv file. So now I just have to go about parsing this into usable data, and this is where I ask for your help as I can't quite think of a good way to go about it.

Should I dump the data into a database? If so, how exactly would I store it? Do I create a table for each dump, or just have one large table that I then store the insert date on each row (so I can limit myself to a specific dump by a where clause (where insert_date = 0608) or something).

They print and mail lots of cards, and they actually like stats gathered for a specific month on multiple occasions, to see how quickly people are "complying". For example, they will print a list two months in advance of a month, one month in advance, and then one, two, and six months after.

Unless you're already really familiar with databases, I wouldn't bother with that. If it's low-volume enough that you can do it by hand right now you should be able to just store the .csv files somewhere and read them each time you want to process them. Python has an excellent CSV parsing module - I'd just save the .csv file into a directory tree organized by date, and write a Python script to read them and calculate stats.

EDIT: it all depends on what tools you're familiar with. If you already have some experience with databases, import the .csv files into SQLite (so you don't need to run a server or anything); if you're good with Excel macros, import them into that. I'm most familiar with programming/Python scripting, so that's what came to mind first.

JoeNotCharles fucked around with this message at 22:52 on May 22, 2008

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

chocojosh posted:

Josh's random thoughts of the days while working on "Yet another boring web page in this enterprise application".

1) The standard of using only up to 80 columns seems to be quite outdated. I had a prof who actually took off marks for this. My monitor supports up to 140 columns (visual studio 2003) at the default font and 1280*1024 resolution. Now, I know different people use different text editors, different font sizes, and so on, but could we please update the standard to 120/130? And then actually ENFORCE it so that I don't have to read stored procedures with lines of 200+ characters.

No, absolutely not. If the file took the entire width of the screen you couldn't put two files side-by-side for comparison.

quote:

2) Is it normal that I don't use switch statements? I just find if/else if/else if/else much easier to read and less verbose than a switch statement. The only time I have used a switch statement is for a WinMain loop.. and that's because it's the convention I see everywhere.

As long as you're not repeating an expression in every test, that's fine.

HB posted:

Aren't case statements faster than long else-if chains?

No, because the compiler's perfectly capable of optimizing.

JoeNotCharles fucked around with this message at 17:26 on May 29, 2008

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

6174 posted:

There is probably a better way to do it, but you could do something like
code:
mv `ls -t1 DHR* | head -n 1` newdir/DHR.xls
The -t1 on ls sorts by last modified and puts the resulting files each on their own line. Since you want the most recent only, you take the first line of the results, hence the head command. Finally that is back tick escaped so it will execute before the mv command.

That checks the actual time the file was written, though - I think he wanted to sort by the date in the filename. (Makes a difference if the whole thing was backed up or copied, for instance, which might give them all the same last modified date.)

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
My vague impression (not counting web development, since I know nothing about it):

- on Windows, absolutely everybody uses Visual Studio, except the Java people who use Eclipse
- on Mac, 80% of people use Xcode and the other 20% are Unix refugees who use command-line tools
- on Unix, it's very fragmented: some people use Eclipse (even for non-Java stuff), some people use KDevelop, some people use specialized IDE's for their own particular task or language, but probably a majority use the commandline and VIM or Emacs.

I would say Windows is still the most common, followed by Unix and then Mac trailing way behind.

If you're wondering which to start with, I'd recommend learning on the command line on Mac or Linux, because then Visual Studio/Xcode/whatever is just one more front-end instead of being the only way you know where to work. It's a lot harder moving the other way if you're used to Visual Studio doing a whole bunch of the work for you.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
You know, I'm not sure exactly why I get the results I do, but:

code:
$ ./foobar -pants
this is a test
file1
file2
$ for i in `./foobar -pants`; do echo $i; done
this
is
a
test
file1
file2
$ for i in `./foobar -pants`; do echo "$i"; done
this
is
a
test
file1
file2
Yeah, you knew that. Here's something that works:

code:
$ for i in "`./foobar -pants`"; do echo "$i"; done
this is a test
file1
file2
Here's something that doesn't, and I'm not sure why not:

code:
$ for i in "`./foobar -pants`"; do echo $i; done
this is a test file1 file2

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

myownsavior posted:

Is trying to learn Objective C (for use w/ XCode and Cocoa) a terrible idea if I don't know anything about the C language?

I've heard people recommend it, and others say you're doing yourself a big disservice by not learning C first.

I'm trying to learn an OOP language this summer, and the only programming experience I have lies in a bit of Pascal, Perl, and PHP.

I'd say you'll probably find it easier without knowing C, because you won't be bouncing off the Smalltalk-isms saying, "But, but, that's nothing like C!"

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Cody Watts posted:

Has anyone worked with this problem before? Can anyone think of a way around it? So far my best guess would be to write the location of the .exe to the registry, and then read and use that value as the working directory when the program starts up. But I'm hoping there's an easier way...

The standard way on Unix is to look at argv[0], which has the full path to the executable. I'm not sure if Windows does the same or just has the filename, but it's work a try. (Of course, on Linux this is usually pretty useless because all the executables are together in /usr/bin.)

I think it's pretty standard to have the installer write the locations of data files to the registry, though. Old CD-ROM games used to do this because they'd install some data files and leave others on the CD - I remember tricking them into doing full installs by copying everything off the CD and then changing the paths in the registry.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Mustach posted:

Not necessarily. I put an argv-printing program in a directory in my path and get whatever string that I call the program as:

Uh, you're right, I don't know what I was thinking. This is how things like busybox work - you symlink the same executable to a bunch of different names, and then check which function of the program to run by checking argv[0] to see which name was used to invoke it.

It still might work in this case, though, because it's the OS filling in the file path so I'd assume it'd use the absolute path.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Scaevolus posted:

Are you trying to optimize something in Python? Maybe you should look into Pyrex or some similar tool before trying to parallelize it.

Python isn't really designed for fast number crunching.

The NumPy people disagree. (No, wait, they agree, but they fixed it by extending the language with native modules.)

Anyway, make sure you're using NumPy for your genetic algorithms and such because it'll fix many performance problems right off the bat and contain infrastructure for fixing the rest.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

magicalblender posted:

My bash script looks very unusual and won't run anymore. The whole thing would break tables, so here's a representative snippet instead:
code:
MLH Z
pTU~IN"@@xI
?!l04vat:ݝK:mk
2 hK-3ÎUUfuqYv...
... And so on, for seventy more lines. What the heck is this stuff?

Type "file name-of-script" and it'll tell you what the OS thinks the script is. If it's tarred or zipped or something, that should be a recognizable file format - if it just says "binary data" it's nothing the OS knows about.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Free Bees posted:

I found out that Windows doesn't support forking, but it must have something similar.

Ha ha ha. How naive.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Coconut Pete posted:

This is not exactly a programming question, but it is related to programming:

If you are contracted to build a web application, say a CMS or whatever, how do you feel about building it with a framework, such as CodeIgniter for PHP or Django or whatever, not counting if the client specifically requests it?

I've always kind of wondered, do you use CodeIgniter, or since you are selling the application as your own to the client, should you write all of the code by hand? Is using a framework "cheating" when selling an application?

Hell no - the client's paying you for the end result, anything you can do to lessen the work on your end is 100% ok. (Where the "end result" includes maintainability, so don't think I'm advocating taking stupid shortcuts and hardcoding things.)

You're not selling every bit of code as being your own, you're selling the entire package. You do have to make sure the license terms on all the components you assemble allow you to resell them, but frameworks should all be ok with that, because that's what they're for.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

ashgromnies posted:

Why does the command line version of md5 on my OS X laptop give me different results than the Javascript implementation at http://pajhome.org.uk/crypt/md5/ ? Since there's an RFC for md5, shouldn't they be the same?

Is one including the newline at the end of the line and one isn't?

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Counter Punch posted:

I'm working on a way to transfer data from an excel spreadsheet into an old NetTerm interface.

If the data is in 27 cells across a row, I should be able to copy the entire row and then hit paste in NetTerm to transfer it all. Sometimes NetTerm takes all the data... other times it hiccups midway through and stops.

I think the problem is that copying and pasting the data passes it through too quickly for the NetTerm system to respond properly.

Is there a way to slow down the speed at which data is copied and pasted?

I'm not familiar with NetTerm, but it might be easy to write a small app in Python or something which just watches for anything copied to the clipboard, reads it all, and then writes it back to the clipboard in smaller chunks with a pause between each chunk. I'd use PyQt for this because the Qt clipboard API's pretty easy to use, but that's because I'm already familiar with it and I have it set up - the Windows clipboard API is easy to use to so a small VB script might be just as good.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Jam2 posted:

How good do ones math skills need to be to excel at programming?

Your logic skills have to be excellent, but higher math doesn't matter so much unless you're specifically doing math programming.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Ugg boots posted:

Just tried it out, and it doesn't seem to be able to set the cursor globally. It worked while the cursor was over my application's window, though.

Off the top of my head, can you give your application a transparent window that covers the entire screen? (Bet that wouldn't work well on multi-head systems, though.)

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Jarl posted:

I started from scratch and now I don't have the problem. The compiler kept telling me that I should put a ';' before '*' which made no sense.

You missed a ; in an earlier line and the * was the first point the compiler knew for sure needed to be a new statement.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Jarl posted:

I should ofc have realized that the function pointers wasn't wrong, but I had just started from one end of the error list. 86 errors. I should have thought something else was wrong.

This is why it's a good idea to start at the beginning of the error list and, when you fix something that looks like it'll have ripple effects, just ignore the rest of the list and recompile. Usually a big chunk of them will go away. If you start at the end you might be looking at errors that were caused by earlier errors.

(Assuming your project compiles quickly so it's faster to recompile and get a new error list than to go through the rest of the errors and manually skip the ones you know aren't valid anymore, that is.)

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

SiLk-2k5 posted:


Question: Besides looking cleaner, what is the speed performance benefit of switch statements versus if/then/else arguments - and at what point does this become noticeable?

None whatsoever.

The only difference between switch and if is that switch only evaluates the condition once, and if evaluates it for each "else if" clause. When the condition is a simple variable like this, there's nothing to evaluate so there's no difference at all.

Also, if the condition is a complex expression or a function call that the compiler can determine returns the same result every time and has no side effects, any decent compiler will optimize it out so it only gets evaluated once anyway.

Finally, this is a trivial change to make later, so when you've finished writing and debugging your program and the last problem with it is that it's slow, and you track down the slowness to this particular section of code, then you can start wondering whether changing between if and switch will fix it. (It won't.)

quote:

I have a long as hell subroutine (one case for each of the 96 possibles), but I figured that the switch/case was the way to go. That being said - I'm going to be calling this routine about 3000 times per day.

96 possible values? 3000 times per day? Miniscule. You've now wasted more time thinking about this than you could ever possibly save by optimizing.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

floWenoL posted:

This is so off-base it's not even funny. :psyduck:

Really? How does it work then?

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.
Bah, I didn't even notice we were talking about strings and not ints.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

kruna posted:

I have a question about C++. First though I wanna provide some of my background so you know where I'm coming from. Basically I studied Java for 2 years in high school, then after that I studied some C++ on my own. I can read C++ very well and I've done some programming, but I haven't actually done any programming in a while. Recently I got hired at my university to help a professor with her physics research. I run and maintain this clunky Fortran (I learned on my own from the ground up) program we use to crunch numbers, Fortran is great for number crunching but I just don't feel comfortable doing some things with it. And well, I think I could save us some time if I could program something on top of Fortran, using C++. So I need someone to point me in the right direction I need to go to learn how to run another program via C++. Just some commands and a tutorial link would be greatly appreciated. I can figure out the rest on my own probably. Thanks in advance goons

I'd say you're best-off using Python as the high-level controller that launches the Fortran tasks. It's really easy to pick up, much less cryptic than C++ and good for writing things rapidly. There might be a specific Python-Fortran interface, but if not, use the subprocess module.

If you really want to use C++, I'd suggest using Qt and the QProcess class which is cross-platform and has a nice clean, high-level API.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

tripwire posted:

Blergh, a related question: in perl compatible RE you can group things together but avoid capturing substrings there by putting a question mark and a colon after the left parenthesis.

So if your expression is "(?:abc)(123)" without quotes, and you match the string "abc123" you would expect that it only captures the substring "123".

How do you do this without perl compatible RE? I'm trying to go through the reference for regex.h but I'm just getting dumbfounded and I'm sure someone must know this off the top of their head.

I don't know, but can't you just ignore \1 and just look at \2?

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

tripwire posted:

Well it doesn't absolutely have to be done with regular expressions, but how would I validate the URI without them? I guess I could make a big wack of if statements that do roughly the same thing, it just seems kludgy.

You find a series of if statements more kludgy than (/(?:[^\r\n/ ]+(?:/[^\r\n/ ]+)*)?)? That's crazy talk.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

the talent deficit posted:

Is there a cross platform way to get the rgb value of a specific pixel displayed on screen?

The pixel may not be constrained to a certain window, unfortunately. I also need a solution that doesn't rely on dumping screenshots. Language doesn't really matter, but C or Python would be ideal. I also don't really care about OSX, but it would be nice if it worked there too.

PyQt (or use the C++ version directly if you have problems with the Python wrapper). Works on Qt, Mac and Linux. I'm not sure what you mean by "dumping screenshots", but I assume you mean you can't save it to an image on disk and then look at the image. The following code will grab the entire screen into a QPixmap in memory and then you get the individual pixel value:

code:
QPixmap::grabWindow(QApplication::desktop().winId()).toImage().pixel(x, y);

Adbot
ADBOT LOVES YOU

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

Triple Tech posted:

I was told this was a stupid idea because it didn't relate to state at all. Like, the functions don't necessarily change the concept, or anything else for that manner (again, functional, stateless).

I'm trying to see if there's like an OOP rule of thumb that will tell me who was right here.

e: spelling

I would say it depends on the pattern of use - if you're always going to be using several of them at around the same time, so you can instantiate the class and then use it over and over, put them in a class. If you'd end up with a common pattern of "Manipulator m(object); m.some_function()" then just put them in a namespace instead.

It might make most sense to add them directly to the object, though.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply