问:
How can I create a unique popup menu that I can use alongside the default context_menu?
(Plugin Development) (Sublime) (Python) (.sublime-menu)

I am currently looking for a way to create a unique context_menu that does not rely on any of the default '.sublime-menu' files already in existence.
I would just use the regular context_menu, but I have that pretty well filled up already. And I would like different buttons for different menus.

This is my current right click menu:

My current context_menu :

I would like to create another dynamic menu similar to this menu, but one that is not dependent on the main/context.sublime-menu, and is activated by using the key/mouse combination ctrl+button4 (which I already have set up).

```<code>{
  "button": "button4",
  "count": 1,
  "modifiers": ["ctrl"],
  "command": "quick_click"
}
</code>```

I have looked at show_popup_menu() as an option and have used the paste_from_history.py file as a sort of reference.

Class PasteFromHistoryCommand(sublime_plugin.TextCommand):
from Sublime\Packages\Default.sublime-package.zip\paste_from_history.py

However, the only thing that menu seems to do, is to take the selection which has been highlighted from a list, and pass it to a text variable which is then passed to the text command 'paste'.

i.e.

```<code>g_clipboard_history.push_text(text)
sublime.set_clipboard(text)
self.view.run_command("paste")
</code>```

show_popup_menu(items, on_done, flags) has the fields ‘items’, ‘on_done’, ect. And I do not know what these mean or how to use them.

I have tried code like this: (And I get no feedback whatsoever)

```<code>class QuickClickCommand(sublime_plugin.TextCommand):
  def run(self, view):
    self.view.show_popup_menu (
      [
        "Select All",
        "Swap Case"
      ],
      [
        self.view.run_command("select_all"),
        self.view.run_command("swap_case")
      ],
      ["1", "2"]  // ← with or without this option
    )
</code>```

But when I use the following code ►

```<code>class QuickClickCommand(sublime_plugin.TextCommand):
  def run(self, view):
    self.view.show_popup_menu (
      ["Item 1", "Item 2"], ["1", "2"]
    )
</code>```

► I get a context menu with 2 items - neither of which do a single thing when pressed upon.

A type of context menu :

I’ve tried several combinations - nothing seems to work, and I cannot find information on this topic.

As you can see I have a plugin:

class QuickClickCommand(sublime_plugin.TextCommand)

And I access that plugin by selecting ctrl+button4

```<code>{
    "button": "button4",
    "count": 1,
    "modifiers": ["ctrl"],
    "command": "quick_click"
}
</code>```

Is it possible to create my own quickclick.sublime-menu file or am I stuck using the default context_menu.sublime-menu?

Any links, suggestions, or explanations of how
show_popup_menu(items, on_done) is used would be appreciated.

Here is what the user docs say about it:

Shows a pop up menu at the caret, to select an item in a list.

on_done will be called once, with the index of the selected item.

If the pop up menu was cancelled, on_done will be called with an argument of -1.

Items is an array of strings.

Flags currently has no option.

When I use the code below: I get the following result.

```<code>class QuickClickCommand(sublime_plugin.TextCommand):
  def run(self, view):
    self.view.show_popup('Hello, <b>World!</b><br>
    <a href="moo">Click Me</a>', on_navigate=print)
    self.view.show_popup_menu (["Item 1", "Item 2"], ["1", "2"])
</code>```

A menu pops up.

Popup Menu :

Once I select any of these 2 Items, I get a panel with the words 'Hello World' and a 'Click Me' link.

Hello, World! Panel :

Once clicking 'Click Me' - 'Hello, World' - will propagate itself to the console.

Is there a way to make my own custom menu in sublime (aside from adding content to the 11 other possible menus that are available upon instillation)?

Thank you for your patients in reading this and any time you might spend on replying to me.

答:
The documentation for view.show_popup_menu() says this:

That is, the method takes a list of strings to display in the menu as a first argument and a function that will be called when the user picks an item as the second argument; that function will be passed the index of the item that the user selected.

In your example code, your second argument is not a function, it's another list of things. You don't get any direct feedback but that's only because Sublime is eating the error when it tries to invoke the callback and fails.

The third argument has no effect on anything because as outlined in the documentation, even though it's supposed to be flags it is currently ignored.

Your question also references the paste_from_history command that uses this API endpoint, and the relevant code line is this:

self.view.show_popup_menu(keys, lambda choice_index: self.paste_choice(choice_index))
```

<p>That's a hint that the second argument is a function (in this case a lambda) which gets provided the index that was chosen when the user picked the item. </p>

<p>The takeaway from this is that unlike standard menus, when you use <code>view.show_popup_menu()</code> all it does is open a menu at the caret location in the window to show the user options, and when they pick one, you get told which one they picked. If the menu is dismissed without being selected, you get told that as well (by the selected item being <code>-1</code>, which is not a valid index).</p>

<p>If you want to run commands from a menu like this, you want something like the following instead:</p>

<pre class="lang-py prettyprint-override"><code>import sublime
import sublime_plugin

class QuickClickCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        items = [
            {"caption": "Echo stuff", "command": "echo", "args": {"a": True}},
            {"caption": "Select All", "command": "select_all"},
            {"caption": "Swap Case", "command": "swap_case"},
        ]
        self.view.show_popup_menu(
            [item["caption"] for item in items],
            lambda idx: self.pick(idx, items))

    def pick(self, idx, items):
        if idx >= 0:
            command = items[idx].get("command")
            args = items[idx].get("args")
            self.view.window().run_command(command, args)
</code>```

First, there is a list of the commands that you want to be able to execute, outlined as objects that specify a caption (what you want to see in the menu), the command (the actual command to execute) and the args (any arguments the command might happen to take or require).

We invoke show_popup_menu and pass to it a list of strings that is the captions for all of the items in the list using a list comprehension. The second argument is the callback that will be called when the user cancels the menu or picks an item. We specify that it should be called given the index of the item that the user picked, as well as the original list of items.

When an item is chosen, pick() is invoked and given the index of the item chosen. If that's -1, then the user closed the menu and so we do nothing. Otherwise, we use the index provided to get the command and arguments (if any) from the original list of items, and then run that command.

This uses self.view.window().run_command() and not self.view.run_command() because a view can only execute commands that modify the buffer; thus it's generally better to use the window to run the command instead because it can run all commands.

Body:
(Plugin Development) (Sublime) (Python) (.sublime-menu)

I am currently looking for a way to create a unique context_menu that does not rely on any of the default '.sublime-menu' files already in existence.
I would just use the regular context_menu, but I have that pretty well filled up already. And I would like different buttons for different menus.

This is my current right click menu:

My current context_menu :

I would like to create another dynamic menu similar to this menu, but one that is not dependent on the main/context.sublime-menu, and is activated by using the key/mouse combination ctrl+button4 (which I already have set up).

{
  "button": "button4",
  "count": 1,
  "modifiers": ["ctrl"],
  "command": "quick_click"
}

I have looked at show_popup_menu() as an option and have used the paste_from_history.py file as a sort of reference.

Class PasteFromHistoryCommand(sublime_plugin.TextCommand):
from Sublime\Packages\Default.sublime-package.zip\paste_from_history.py

However, the only thing that menu seems to do, is to take the selection which has been highlighted from a list, and pass it to a text variable which is then passed to the text command 'paste'.

i.e.

g_clipboard_history.push_text(text)
sublime.set_clipboard(text)
self.view.run_command("paste")

show_popup_menu(items, on_done, flags) has the fields ‘items’, ‘on_done’, ect. And I do not know what these mean or how to use them.

I have tried code like this: (And I get no feedback whatsoever)

class QuickClickCommand(sublime_plugin.TextCommand):
  def run(self, view):
    self.view.show_popup_menu (
      [
        "Select All",
        "Swap Case"
      ],
      [
        self.view.run_command("select_all"),
        self.view.run_command("swap_case")
      ],
      ["1", "2"]  // ← with or without this option
    )

But when I use the following code ►

class QuickClickCommand(sublime_plugin.TextCommand):
  def run(self, view):
    self.view.show_popup_menu (
      ["Item 1", "Item 2"], ["1", "2"]
    )

► I get a context menu with 2 items - neither of which do a single thing when pressed upon.

A type of context menu :

I’ve tried several combinations - nothing seems to work, and I cannot find information on this topic.

As you can see I have a plugin:

class QuickClickCommand(sublime_plugin.TextCommand)

And I access that plugin by selecting ctrl+button4

{
    "button": "button4",
    "count": 1,
    "modifiers": ["ctrl"],
    "command": "quick_click"
}

Is it possible to create my own quickclick.sublime-menu file or am I stuck using the default context_menu.sublime-menu?

Any links, suggestions, or explanations of how
show_popup_menu(items, on_done) is used would be appreciated.

Here is what the user docs say about it:

Shows a pop up menu at the caret, to select an item in a list.

on_done will be called once, with the index of the selected item.

If the pop up menu was cancelled, on_done will be called with an argument of -1.

Items is an array of strings.

Flags currently has no option.

When I use the code below: I get the following result.

class QuickClickCommand(sublime_plugin.TextCommand):
  def run(self, view):
    self.view.show_popup('Hello, World!

    Click Me', on_navigate=print)
    self.view.show_popup_menu (["Item 1", "Item 2"], ["1", "2"])

A menu pops up.

Popup Menu :

Once I select any of these 2 Items, I get a panel with the words 'Hello World' and a 'Click Me' link.

Hello, World! Panel :

Once clicking 'Click Me' - 'Hello, World' - will propagate itself to the console.

Is there a way to make my own custom menu in sublime (aside from adding content to the 11 other possible menus that are available upon instillation)?

Thank you for your patients in reading this and any time you might spend on replying to me.

Body:
The documentation for view.show_popup_menu() says this:

That is, the method takes a list of strings to display in the menu as a first argument and a function that will be called when the user picks an item as the second argument; that function will be passed the index of the item that the user selected.

In your example code, your second argument is not a function, it's another list of things. You don't get any direct feedback but that's only because Sublime is eating the error when it tries to invoke the callback and fails.

The third argument has no effect on anything because as outlined in the documentation, even though it's supposed to be flags it is currently ignored.

Your question also references the paste_from_history command that uses this API endpoint, and the relevant code line is this:

self.view.show_popup_menu(keys, lambda choice_index: self.paste_choice(choice_index))

That's a hint that the second argument is a function (in this case a lambda) which gets provided the index that was chosen when the user picked the item.

The takeaway from this is that unlike standard menus, when you use view.show_popup_menu() all it does is open a menu at the caret location in the window to show the user options, and when they pick one, you get told which one they picked. If the menu is dismissed without being selected, you get told that as well (by the selected item being -1, which is not a valid index).

If you want to run commands from a menu like this, you want something like the following instead:

import sublime
import sublime_plugin

class QuickClickCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        items = [
            {"caption": "Echo stuff", "command": "echo", "args": {"a": True}},
            {"caption": "Select All", "command": "select_all"},
            {"caption": "Swap Case", "command": "swap_case"},
        ]
        self.view.show_popup_menu(
            [item["caption"] for item in items],
            lambda idx: self.pick(idx, items))

    def pick(self, idx, items):
        if idx >= 0:
            command = items[idx].get("command")
            args = items[idx].get("args")
            self.view.window().run_command(command, args)

First, there is a list of the commands that you want to be able to execute, outlined as objects that specify a caption (what you want to see in the menu), the command (the actual command to execute) and the args (any arguments the command might happen to take or require).

We invoke show_popup_menu and pass to it a list of strings that is the captions for all of the items in the list using a list comprehension. The second argument is the callback that will be called when the user cancels the menu or picks an item. We specify that it should be called given the index of the item that the user picked, as well as the original list of items.

When an item is chosen, pick() is invoked and given the index of the item chosen. If that's -1, then the user closed the menu and so we do nothing. Otherwise, we use the index provided to get the command and arguments (if any) from the original list of items, and then run that command.

This uses self.view.window().run_command() and not self.view.run_command() because a view can only execute commands that modify the buffer; thus it's generally better to use the window to run the command instead because it can run all commands.


来源: stackexchange

问:
Can't access variable (array) from another function (defined in global scope)
I'd like to use a variable (array) from another function. I already defined it in global scope, but it doesn't work..

Here is my code for better understanding:

```<code>var globalData = '';
var data = '';

$.getJSON('https://...' + data[x].id + '.json', function(data) {

    globalData = data;
    data = globalData.name;

    console.log(data); // works just fine

    if (condition === 1) {
        function2(); // calls this function
    } else {
        function3();
    }
});

function function2() {
    console.log(data); // just an empty line
    console.log(globalData); // UPDATE: works just fine
}
</code>```

答:
The problem is that the variable data is being shadowed within the callback function.

```<code>function(data) {

    globalData = data;
    data = globalData.name;

    console.log(data); // works just fine
...
</code>```

So function(data) established a local variable scoped to the function. Then the bizarre assign and reassign thing happens. You want to believe you are manipulating the global version of data but you are only dealing with the scoped version.

So, the variable data must be passed to the function.

If you prefer to use the global (not recommended), all you have to do is change the function declaration from (data) to some other identifier.

ContentLicense: CC BY-SA 4.0

Body:
I'd like to use a variable (array) from another function. I already defined it in global scope, but it doesn't work..

Here is my code for better understanding:

var globalData = '';
var data = '';

$.getJSON('https://...' + data[x].id + '.json', function(data) {

    globalData = data;
    data = globalData.name;

    console.log(data); // works just fine

    if (condition === 1) {
        function2(); // calls this function
    } else {
        function3();
    }
});

function function2() {
    console.log(data); // just an empty line
    console.log(globalData); // UPDATE: works just fine
}

Body:
The problem is that the variable data is being shadowed within the callback function.

function(data) {

    globalData = data;
    data = globalData.name;

    console.log(data); // works just fine
...

So function(data) established a local variable scoped to the function. Then the bizarre assign and reassign thing happens. You want to believe you are manipulating the global version of data but you are only dealing with the scoped version.

So, the variable data must be passed to the function.

If you prefer to use the global (not recommended), all you have to do is change the function declaration from (data) to some other identifier.


问:
I want to change the size of any button clicked
I have used 9 Buttons and I want to be bigger on anyone clicked, and if any of the exit modes came out, they would return to their default.
All these buttons are used in a grid-layout
I have used 9 Buttons and I want to be bigger on anyone clicked you can see example View in here

this is my source code

```<code>public class MainActivity extends AppCompatActivity implements Animation.AnimationListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        content = 1;

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

//add category
        searchButton = (Button) findViewById(R.id.addCategory);

        searchButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final View promptsView = getLayoutInflater().inflate(R.layout.prompts_category, null);

                AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);
                alertDialogBuilder.setView(promptsView);
                final AlertDialog dialog = alertDialogBuilder.create();

                dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
                dialog.show();
                WindowManager.LayoutParams lp = new WindowManager.LayoutParams();

                lp.copyFrom(dialog.getWindow().getAttributes());
                lp.width = 800;
                lp.height = 675;
                dialog.getWindow().setAttributes(lp);

                dialog.getWindow().clearFlags(WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW);

                addCategoryButton = (Button) dialog.findViewById(R.id.addCatButton);
                insertCategoryName = (EditText) dialog.findViewById(R.id.insertCategoryName);

                gridColorsCategory = (GridLayout) dialog.findViewById(R.id.gridColorsCategory);

                setSingleEvent(gridColorsCategory);
                addCategoryButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        insertCategoryName.getText().toString();

                    }
                });
            }
        });

    }

    private void setSingleEvent(GridLayout gridColorsCategory) {
        for (int i = 0; i < gridColorsCategory.getChildCount(); i++) {
            final Button button = (Button) gridColorsCategory.getChildAt(i);
            final int finalI = i;

            final ViewGroup.LayoutParams layoutParams = button.getLayoutParams();

            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                   }
                }
            });
        }

    }
</code>```

答:
you can use this method to resize your button

```<code>private void resizeView(View view, int newWidth, int newHeight) {
    try {
        Constructor<? extends LayoutParams> ctor = view.getLayoutParams().getClass().getDeclaredConstructor(int.class, int.class);
        view.setLayoutParams(ctor.newInstance(newWidth, newHeight));
    } catch (Exception e) {
        e.printStackTrace();
    }
}
</code>```

and if the default is wrap_content

```<code>  private void resizeDefault(View view) {
        try {
          ViewGroup.LayoutParams params = textView.getLayoutParams();
          params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
          params.width = ViewGroup.LayoutParams.WRAP_CONTENT;
          view.setLayoutParams(params);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
</code>```

Body:
I have used 9 Buttons and I want to be bigger on anyone clicked, and if any of the exit modes came out, they would return to their default.
All these buttons are used in a grid-layout
I have used 9 Buttons and I want to be bigger on anyone clicked you can see example View in here

this is my source code

public class MainActivity extends AppCompatActivity implements Animation.AnimationListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        content = 1;

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

//add category
        searchButton = (Button) findViewById(R.id.addCategory);

        searchButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final View promptsView = getLayoutInflater().inflate(R.layout.prompts_category, null);

                AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);
                alertDialogBuilder.setView(promptsView);
                final AlertDialog dialog = alertDialogBuilder.create();

                dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
                dialog.show();
                WindowManager.LayoutParams lp = new WindowManager.LayoutParams();

                lp.copyFrom(dialog.getWindow().getAttributes());
                lp.width = 800;
                lp.height = 675;
                dialog.getWindow().setAttributes(lp);

                dialog.getWindow().clearFlags(WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW);

                addCategoryButton = (Button) dialog.findViewById(R.id.addCatButton);
                insertCategoryName = (EditText) dialog.findViewById(R.id.insertCategoryName);

                gridColorsCategory = (GridLayout) dialog.findViewById(R.id.gridColorsCategory);

                setSingleEvent(gridColorsCategory);
                addCategoryButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        insertCategoryName.getText().toString();

                    }
                });
            }
        });

    }

    private void setSingleEvent(GridLayout gridColorsCategory) {
        for (int i = 0; i < gridColorsCategory.getChildCount(); i++) {
            final Button button = (Button) gridColorsCategory.getChildAt(i);
            final int finalI = i;

            final ViewGroup.LayoutParams layoutParams = button.getLayoutParams();

            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                   }
                }
            });
        }

    }

Body:
you can use this method to resize your button

private void resizeView(View view, int newWidth, int newHeight) {
    try {
        Constructor<? extends LayoutParams> ctor = view.getLayoutParams().getClass().getDeclaredConstructor(int.class, int.class);
        view.setLayoutParams(ctor.newInstance(newWidth, newHeight));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

and if the default is wrap_content

  private void resizeDefault(View view) {
        try {
          ViewGroup.LayoutParams params = textView.getLayoutParams();
          params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
          params.width = ViewGroup.LayoutParams.WRAP_CONTENT;
          view.setLayoutParams(params);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


问:
How to detect the stock Android browser
Navigating to http://whatsmyuseragent.com/ shows me my stock Android browser on my Galaxy Nexus running 4.2.1 has the user agent

```<code>Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.34 Safari/534.24
</code>```

There is nothing in this user agent that allows me to uniquely detect that it is a stock Android browser. The Chrome for Android app at least has android in the UA. Is there any way for me to detect the stock Android app?

答:
If you need a regular expression:</p>

```<code>/Android[\s|/].+(AppleWebKit|Nokia)(.(?!Chrome|Presto|UCBrowser))+.$/gi
</code>```

ContentLicense: CC BY-SA 3.0

Title: How to detect the stock Android browser

Body:
Navigating to http://whatsmyuseragent.com/ shows me my stock Android browser on my Galaxy Nexus running 4.2.1 has the user agent

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.34 Safari/534.24

There is nothing in this user agent that allows me to uniquely detect that it is a stock Android browser. The Chrome for Android app at least has android in the UA. Is there any way for me to detect the stock Android app?

Body:
If you need a regular expression:

/Android[\s|/].+(AppleWebKit|Nokia)(.(?!Chrome|Presto|UCBrowser))+.$/gi


问:
What does float *a[]; declare in c?
Suppose float *a[]; is declared in the main method n c. I'm trying to learn about pointers and understand what the above means.

I'm guessing it declares a pointer to the first element of that array a[].
But a[] doesn't have any elements..
I am really confused.

Thanks anyone who helps.

答:
An empty array size can be given if the compiler does not need to know the size of the array.

This is the case in two situations:

extern declarations

function argument types

Example 1:

```<code>extern float *a[];
</code>```

Using the line above you tell the C compiler that there is an array of float * elements named a in some C file.

Example 2:

```<code>void someFunction(float *a[])
</code>```

Using that line you specify that the argument type is an array of float * elements.

Both will work because the compiler does not need to know the size of an array to access it. The compiler only needs to know the size to reserve memory for the array.

In both cases (extern and function argument) you will only reference to an existing array (that already occupies memory). Therefore no memory needs to be reserved and the compiler does not need to know the size of the array.

Title: What does float *a[]; declare in c?

Body:
An empty array size can be given if the compiler does not need to know the size of the array.

This is the case in two situations:

extern declarations

function argument types

Example 1:

extern float *a[];

Using the line above you tell the C compiler that there is an array of float * elements named a in some C file.

Example 2:

void someFunction(float *a[])

Using that line you specify that the argument type is an array of float * elements.

Both will work because the compiler does not need to know the size of an array to access it. The compiler only needs to know the size to reserve memory for the array.

In both cases (extern and function argument) you will only reference to an existing array (that already occupies memory). Therefore no memory needs to be reserved and the compiler does not need to know the size of the array.


问:
PhotoPicker discovery error: Error Domain=PlugInKit Code=13
I'm trying to display an image from the photo library in a UIImageView

The full error is:

2017-06-09 21:55:59.063307+0200 firstapp2.0[12873:1120778] PhotoPicker
  discovery error: Error Domain=PlugInKit Code=13 "query cancelled"
  UserInfo={NSLocalizedDescription=query cancelled}

My code is included below:

```<code>import UIKit

class ViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate{

    @IBOutlet weak var pic: UIImageView!
    @IBOutlet weak var text: UILabel!

    var chosenImage : UIImage!

    override func viewDidLoad() {
        super.viewDidLoad()
        pic.isUserInteractionEnabled = true;
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [AnyHashable: Any]) {
        var chosenImage = info[UIImagePickerControllerEditedImage]
        self.pic!.image = chosenImage as! UIImage
        picker.dismiss(animated: true, completion: nil)
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }

    @IBAction func tap(_ sender: Any) {
        self.text.text = "Kreason"
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
        imagePicker.allowsEditing = false
        self.present(imagePicker, animated: true, completion: nil)
    }
}
</code>```

答:
Swift 5 and Above: </p>

```<code>import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    @IBOutlet weak var pic: UIImageView!
    @IBOutlet weak var text: UILabel!

    var chosenImage : UIImage!

    override func viewDidLoad() {
        super.viewDidLoad()
        pic.isUserInteractionEnabled = true
    }

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        guard let image = info[.editedImage] as? UIImage else { return }
        dismiss(animated: true)
        chosenImage = image
        **pic.image = chosenImage**

    }

    @IBAction func tap(_ sender: Any) {
        self.text.text = "Kreason"
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        //imagePicker.dataSource = self
        imagePicker.allowsEditing = false
        self.present(imagePicker, animated: true)

    }
}
</code>```

Body:
I'm trying to display an image from the photo library in a UIImageView

The full error is:

2017-06-09 21:55:59.063307+0200 firstapp2.0[12873:1120778] PhotoPicker
  discovery error: Error Domain=PlugInKit Code=13 "query cancelled"
  UserInfo={NSLocalizedDescription=query cancelled}

My code is included below:

import UIKit

class ViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate{

    @IBOutlet weak var pic: UIImageView!
    @IBOutlet weak var text: UILabel!

    var chosenImage : UIImage!

    override func viewDidLoad() {
        super.viewDidLoad()
        pic.isUserInteractionEnabled = true;
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [AnyHashable: Any]) {
        var chosenImage = info[UIImagePickerControllerEditedImage]
        self.pic!.image = chosenImage as! UIImage
        picker.dismiss(animated: true, completion: nil)
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }

    @IBAction func tap(_ sender: Any) {
        self.text.text = "Kreason"
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
        imagePicker.allowsEditing = false
        self.present(imagePicker, animated: true, completion: nil)
    }
}

Body:
Swift 5 and Above:

import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    @IBOutlet weak var pic: UIImageView!
    @IBOutlet weak var text: UILabel!

    var chosenImage : UIImage!

    override func viewDidLoad() {
        super.viewDidLoad()
        pic.isUserInteractionEnabled = true
    }

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        guard let image = info[.editedImage] as? UIImage else { return }
        dismiss(animated: true)
        chosenImage = image
        **pic.image = chosenImage**

    }

    @IBAction func tap(_ sender: Any) {
        self.text.text = "Kreason"
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        //imagePicker.dataSource = self
        imagePicker.allowsEditing = false
        self.present(imagePicker, animated: true)

    }
}


问:
After adding @ComponentScan to load beans from a jar my controllers isn't scan and i get 404
I have a spring-boot application (Java8, spring-boot 2.1.4-RELEASE).

One of the services in the business layer need to @Autowire a bean from a certain jars in my classpath. In order to achieve that i had to add @ComponentScan({"package.to.my.bean.inside.the.jar"}) and it was magically scanned and wired successfully (this was added to the main spring-boot class which declare the main method).

However, since then my controllers aren't scanned hence the DispatcherServlet is returning 404 for every request i trigger (default dispatcher).
Actually my entire spring-boot app annotations is being ignored - no scan is performed.
Just to emphasis - the application worked perfectly before adding the @ComponentScan.

Main spring-boot app class:

```<code>package com.liav.ezer;

// This is the problematic addition that cause the endpoints to stop
// inside a jar in the classpath, in com.internal.jar package resides an
// object which i need to wire at run time
@ComponentScan({"com.internal.jar"})
@SpringBootApplication
public class JobsApplication {
    public static void main(String[] args) {
        SpringApplication.run(JobsApplication .class, args);
        }
}
</code>```

Controller example:

```<code>package com.liav.ezer.controller;

@RestController
@EnableAutoConfiguration
@RequestMapping(path = "/jobs")
public class JobController {

    @GetMapping(path="/create", produces = "application/json")
    @ResponseStatus(HttpStatus.OK)
    String createJob(@RequestParam() String jobName) String jobName){
        return "job created...";
    }
}
</code>```

I tried adding my spring-boot app base package to the list of packages in the @ComponentScan with no luck.
I tried narrowing down the scope of the package declaration to be only on the class which i need with no luck.
Here is the code

答:
If so, remove @ComponentScan, can declare that bean in yourself configuration.
try below

@SpringBootApplication
public class JobsApplication {
    public static void main(String[] args) {
        SpringApplication.run(JobsApplication .class, args);
        }
     @Bean
     public BeanInOtherJar xxBean(){
        return new com.internal.jar.XXX();
     }
}
```

Body:
I have a spring-boot application (Java8, spring-boot 2.1.4-RELEASE).

One of the services in the business layer need to @Autowire a bean from a certain jars in my classpath. In order to achieve that i had to add @ComponentScan({"package.to.my.bean.inside.the.jar"}) and it was magically scanned and wired successfully (this was added to the main spring-boot class which declare the main method).

However, since then my controllers aren't scanned hence the DispatcherServlet is returning 404 for every request i trigger (default dispatcher).
Actually my entire spring-boot app annotations is being ignored - no scan is performed.
Just to emphasis - the application worked perfectly before adding the @ComponentScan.

Main spring-boot app class:

package com.liav.ezer;

// This is the problematic addition that cause the endpoints to stop
// inside a jar in the classpath, in com.internal.jar package resides an
// object which i need to wire at run time
@ComponentScan({"com.internal.jar"})
@SpringBootApplication
public class JobsApplication {
    public static void main(String[] args) {
        SpringApplication.run(JobsApplication .class, args);
        }
}

Controller example:

package com.liav.ezer.controller;

@RestController
@EnableAutoConfiguration
@RequestMapping(path = "/jobs")
public class JobController {

    @GetMapping(path="/create", produces = "application/json")
    @ResponseStatus(HttpStatus.OK)
    String createJob(@RequestParam() String jobName) String jobName){
        return "job created...";
    }
}

I tried adding my spring-boot app base package to the list of packages in the @ComponentScan with no luck.
I tried narrowing down the scope of the package declaration to be only on the class which i need with no luck.
Here is the code


问:
Why is my code not working on more than one thread?
I have been trying to multi-thread my code, it still works, but only uses 15% of my cpu (i have 8 threads, so thats 1 thread).

I have tried many scripts to multi-thread from stack overflow and youtube, but none worked.

```<code>import threading

n=2

def crazy():
    global n
    while True:
        n = n*2
        print(n)

threads = []
for i in range(4):
    t = threading.Thread(target=crazy)
    threads.append(t)
    t.start()
</code>```

The ouput is as expected, but only running on one thread.

答: No CPU speed up can be connected with Global Interpreter Lock (GIL) you  can read about it here https://realpython.com/python-gil/ and google about GIL </p>

Body:
I have been trying to multi-thread my code, it still works, but only uses 15% of my cpu (i have 8 threads, so thats 1 thread).

I have tried many scripts to multi-thread from stack overflow and youtube, but none worked.

import threading

n=2

def crazy():
    global n
    while True:
        n = n*2
        print(n)

threads = []
for i in range(4):
    t = threading.Thread(target=crazy)
    threads.append(t)
    t.start()

The ouput is as expected, but only running on one thread.


问:
Why use functions that just return a constant instead of just using a constant?
I ran into some code on GitHub. https://github.com/codeplea/tinyexpr/blob/master/tinyexpr.c

These lines caught my eye:

```<code>static double pi(void) {return 3.14159265358979323846;}
static double e(void) {return 2.71828182845904523536;}
</code>```

Is there any reason at all to use functions in this case? Why not use constants? You could use preprocessor macros, but that can make debugging harder. I have never seen this before. Is there any benefit of this?

答:
The main reason I can think of is to make it easier to search for where that constant is used.  For example, you search for e( instead of e.

That isn't the case here, however.  The functions are being used, but not called explicitly.

The linked code contains an array of structs:

```<code>typedef struct te_variable {
    const char *name;
    const void *address;
    int type;
    void *context;
} te_variable;

...

static const te_variable functions[] = {
    /* must be in alphabetical order */
    {"abs", fabs,     TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"acos", acos,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"asin", asin,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"atan", atan,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"atan2", atan2,  TE_FUNCTION2 | TE_FLAG_PURE, 0},
    {"ceil", ceil,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"cos", cos,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"cosh", cosh,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"e", e,          TE_FUNCTION0 | TE_FLAG_PURE, 0},
    {"exp", exp,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"fac", fac,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"floor", floor,  TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"ln", log,       TE_FUNCTION1 | TE_FLAG_PURE, 0},
#ifdef TE_NAT_LOG
    {"log", log,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
#else
    {"log", log10,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
#endif
    {"log10", log10,  TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"ncr", ncr,      TE_FUNCTION2 | TE_FLAG_PURE, 0},
    {"npr", npr,      TE_FUNCTION2 | TE_FLAG_PURE, 0},
    {"pi", pi,        TE_FUNCTION0 | TE_FLAG_PURE, 0},
    {"pow", pow,      TE_FUNCTION2 | TE_FLAG_PURE, 0},
    {"sin", sin,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"sinh", sinh,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"sqrt", sqrt,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"tan", tan,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"tanh", tanh,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {0, 0, 0, 0}
};
</code>```

The second member of each struct is a function pointer used to run some math related function, and the values of E and PI are among them.  So it looks like they were defined as functions to conform to this framework.

Body:
I ran into some code on GitHub. https://github.com/codeplea/tinyexpr/blob/master/tinyexpr.c

These lines caught my eye:

static double pi(void) {return 3.14159265358979323846;}
static double e(void) {return 2.71828182845904523536;}

Is there any reason at all to use functions in this case? Why not use constants? You could use preprocessor macros, but that can make debugging harder. I have never seen this before. Is there any benefit of this?

Body:
The main reason I can think of is to make it easier to search for where that constant is used.  For example, you search for e( instead of e.

That isn't the case here, however.  The functions are being used, but not called explicitly.

The linked code contains an array of structs:

typedef struct te_variable {
    const char *name;
    const void *address;
    int type;
    void *context;
} te_variable;

...

static const te_variable functions[] = {
    /* must be in alphabetical order */
    {"abs", fabs,     TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"acos", acos,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"asin", asin,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"atan", atan,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"atan2", atan2,  TE_FUNCTION2 | TE_FLAG_PURE, 0},
    {"ceil", ceil,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"cos", cos,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"cosh", cosh,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"e", e,          TE_FUNCTION0 | TE_FLAG_PURE, 0},
    {"exp", exp,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"fac", fac,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"floor", floor,  TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"ln", log,       TE_FUNCTION1 | TE_FLAG_PURE, 0},
#ifdef TE_NAT_LOG
    {"log", log,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
#else
    {"log", log10,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
#endif
    {"log10", log10,  TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"ncr", ncr,      TE_FUNCTION2 | TE_FLAG_PURE, 0},
    {"npr", npr,      TE_FUNCTION2 | TE_FLAG_PURE, 0},
    {"pi", pi,        TE_FUNCTION0 | TE_FLAG_PURE, 0},
    {"pow", pow,      TE_FUNCTION2 | TE_FLAG_PURE, 0},
    {"sin", sin,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"sinh", sinh,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"sqrt", sqrt,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"tan", tan,      TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {"tanh", tanh,    TE_FUNCTION1 | TE_FLAG_PURE, 0},
    {0, 0, 0, 0}
};

The second member of each struct is a function pointer used to run some math related function, and the values of E and PI are among them.  So it looks like they were defined as functions to conform to this framework.


问:
Getting error after adding web worker with cli command in Angular 8
Angular 8 has added a better support for web workers. I had no luck to get it working. Does someone know what am i doing wrong?

Here is official guide i followed.

With this cli command i generated web worker:

```<code>ng generate webWorker my-worker
</code>```

cli has generated my-worker.worker.ts file and tsconfig.worker.json file,  and updated following files: angular.json, tsconfig.app.json.

After this im getting following error:

```<code>ERROR in node_modules/typescript/lib/lib.dom.d.ts(25,1): error TS6200: Definitions of the following identifiers conflict with those in another file: EventListenerOrEventListenerObject, BlobPart, HeadersInit, BodyInit, RequestInfo, DOMHighResTimeStamp, CanvasImageSource, MessageEventSource, ImageBitmapSource, TimerHandler, PerformanceEntryList, VibratePattern, AlgorithmIdentifier, HashAlgorithmIdentifier, BigInteger, NamedCurve, GLenum, GLboolean, GLbitfield, GLint, GLsizei, GLintptr, GLsizeiptr, GLuint, GLfloat, GLclampf, TexImageSource, Float32List, Int32List, BufferSource, DOMTimeStamp, FormDataEntryValue, IDBValidKey, Transferable, BinaryType, ClientTypes, EndingType, IDBCursorDirection, IDBRequestReadyState, IDBTransactionMode, KeyFormat, KeyType, KeyUsage, NotificationDirection, NotificationPermission, PushEncryptionKeyName, PushPermissionState, ReferrerPolicy, RequestCache, RequestCredentials, RequestDestination, RequestMode, RequestRedirect, ResponseType, ServiceWorkerState, ServiceWorkerUpdateViaCache, VisibilityState, WebGLPowerPreference, WorkerType, XMLHttpRequestResponseType
node_modules/typescript/lib/lib.dom.d.ts(3473,5): error TS2687: All declarations of 'privateKey' must have identical modifiers.
node_modules/typescript/lib/lib.dom.d.ts(3474,5): error TS2687: All declarations of 'publicKey' must have identical modifiers.
node_modules/typescript/lib/lib.webworker.d.ts(25,1): error TS6200: Definitions of the following identifiers conflict with those in another file: EventListenerOrEventListenerObject, BlobPart, HeadersInit, BodyInit, RequestInfo, DOMHighResTimeStamp, CanvasImageSource, MessageEventSource, ImageBitmapSource, TimerHandler, PerformanceEntryList, VibratePattern, AlgorithmIdentifier, HashAlgorithmIdentifier, BigInteger, NamedCurve, GLenum, GLboolean, GLbitfield, GLint, GLsizei, GLintptr, GLsizeiptr, GLuint, GLfloat, GLclampf, TexImageSource, Float32List, Int32List, BufferSource, DOMTimeStamp, FormDataEntryValue, IDBValidKey, Transferable, BinaryType, ClientTypes, EndingType, IDBCursorDirection, IDBRequestReadyState, IDBTransactionMode, KeyFormat, KeyType, KeyUsage, NotificationDirection, NotificationPermission, PushEncryptionKeyName, PushPermissionState, ReferrerPolicy, RequestCache, RequestCredentials, RequestDestination, RequestMode, RequestRedirect, ResponseType, ServiceWorkerState, ServiceWorkerUpdateViaCache, VisibilityState, WebGLPowerPreference, WorkerType, XMLHttpRequestResponseType
node_modules/typescript/lib/lib.webworker.d.ts(85,5): error TS2687: All declarations of 'privateKey' must have identical modifiers.
node_modules/typescript/lib/lib.webworker.d.ts(86,5): error TS2687: All declarations of 'publicKey' must have identical modifiers.
node_modules/typescript/lib/lib.webworker.d.ts(1074,5): error TS2375: Duplicate number index signature.
node_modules/typescript/lib/lib.webworker.d.ts(1360,5): error TS2375: Duplicate number index signature.
node_modules/typescript/lib/lib.webworker.d.ts(1434,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'FormData' must be of type '{ new (form?: HTMLFormElement): FormData; prototype: FormData; }', but here has type '{ new (): FormData; prototype: FormData; }'.
node_modules/typescript/lib/lib.webworker.d.ts(2170,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'Notification' must be of type '{ new (title: string, options?: NotificationOptions): Notification; prototype: Notification; readonly maxActions: number; readonly permission: NotificationPermission; requestPermission(deprecatedCallback?: NotificationPermissionCallback): Promise<...>; }', but here has type '{ new (title: string, options?: NotificationOptions): Notification; prototype: Notification; readonly maxActions: number; readonly permission: NotificationPermission; }'.
node_modules/typescript/lib/lib.webworker.d.ts(4322,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'onmessage' must be of type '(this: Window, ev: MessageEvent) => any', but here has type '(this: DedicatedWorkerGlobalScope, ev: MessageEvent) => any'.
node_modules/typescript/lib/lib.webworker.d.ts(4332,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'location' must be of type 'Location', but here has type 'WorkerLocation'.
node_modules/typescript/lib/lib.webworker.d.ts(4333,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'onerror' must be of type 'OnErrorEventHandlerNonNull', but here has type '(this: DedicatedWorkerGlobalScope, ev: ErrorEvent) => any'.
node_modules/typescript/lib/lib.webworker.d.ts(4335,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'self' must be of type 'Window', but here has type 'WorkerGlobalScope'.
node_modules/typescript/lib/lib.webworker.d.ts(4344,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'navigator' must be of type 'Navigator', but here has type 'WorkerNavigator'.
</code>```

Here is my package.json file:

```<code>    {
  "name": "app-name",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^8.0.0",
    "@angular/cdk": "^8.0.0",
    "@angular/common": "^8.0.0",
    "@angular/compiler": "^8.0.0",
    "@angular/core": "^8.0.0",
    "@angular/fire": "^5.1.3",
    "@angular/forms": "^8.0.0",
    "@angular/material": "^8.0.0",
    "@angular/platform-browser": "^8.0.0",
    "@angular/platform-browser-dynamic": "^8.0.0",
    "@angular/router": "^8.0.0",
    "bootstrap": "^4.3.1",
    "classlist.js": "^1.1.20150312",
    "core-js": "^2.5.4",
    "firebase": "^5.11.1",
    "hammerjs": "^2.0.8",
    "material-design-icons": "^3.0.1",
    "rxjs": "^6.5.2",
    "save": "^2.3.3",
    "smoothscroll-polyfill": "^0.4.3",
    "tslib": "^1.9.0",
    "web-animations-js": "github:angular/web-animations-js#release_pr208",
    "zone.js": "~0.9.1"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.800.1",
    "@angular/cli": "^8.0.1",
    "@angular/compiler-cli": "^8.0.0",
    "@angular/language-service": "^8.0.0",
    "@types/jasmine": "~3.3.0",
    "@types/jasminewd2": "~2.0.6",
    "@types/node": "~12.0.3",
    "codelyzer": "^5.0.1",
    "jasmine-core": "~3.3.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "^4.0.1",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.4",
    "karma-jasmine": "~2.0.1",
    "karma-jasmine-html-reporter": "^1.4.0",
    "protractor": "~5.4.1",
    "ts-node": "~7.0.1",
    "tslint": "~5.11.0",
    "typescript": "^3.4.5"
  }
}
</code>```

Thanks.

答:
I had this issue too, and noticed that in a new Angular 8 project, all tsconfig.*.json files are in the root directory, and there is only the root tslint.json file.

Here's what I did:

Copied tslint.json, tsconfig.app.json, and tsconfig.spec.json from a newly generated CLI 8 project to my project root.

Deleted tslint.json, tsconfig.app.json, and tsconfig.spec.json from the src directory.

Edited tsConfig values in angular.json to look for tsconfig files in project root, instead of in src directory.

If you made any modifications to the tsconfig files generated by the CLI, it might be easier to move them from src to the root, and edit the paths in them. I didn't change the generated files, so I just copied from a new project.

I have no idea what it is about generating a Web Worker and the addition of the tsconfig.worker.json that throws a wrench in an upgraded Angular project. Upgrading from 7 worked fine until I added a worker.

Body:
Angular 8 has added a better support for web workers. I had no luck to get it working. Does someone know what am i doing wrong?

Here is official guide i followed.

With this cli command i generated web worker:

ng generate webWorker my-worker

cli has generated my-worker.worker.ts file and tsconfig.worker.json file,  and updated following files: angular.json, tsconfig.app.json.

After this im getting following error:

ERROR in node_modules/typescript/lib/lib.dom.d.ts(25,1): error TS6200: Definitions of the following identifiers conflict with those in another file: EventListenerOrEventListenerObject, BlobPart, HeadersInit, BodyInit, RequestInfo, DOMHighResTimeStamp, CanvasImageSource, MessageEventSource, ImageBitmapSource, TimerHandler, PerformanceEntryList, VibratePattern, AlgorithmIdentifier, HashAlgorithmIdentifier, BigInteger, NamedCurve, GLenum, GLboolean, GLbitfield, GLint, GLsizei, GLintptr, GLsizeiptr, GLuint, GLfloat, GLclampf, TexImageSource, Float32List, Int32List, BufferSource, DOMTimeStamp, FormDataEntryValue, IDBValidKey, Transferable, BinaryType, ClientTypes, EndingType, IDBCursorDirection, IDBRequestReadyState, IDBTransactionMode, KeyFormat, KeyType, KeyUsage, NotificationDirection, NotificationPermission, PushEncryptionKeyName, PushPermissionState, ReferrerPolicy, RequestCache, RequestCredentials, RequestDestination, RequestMode, RequestRedirect, ResponseType, ServiceWorkerState, ServiceWorkerUpdateViaCache, VisibilityState, WebGLPowerPreference, WorkerType, XMLHttpRequestResponseType
node_modules/typescript/lib/lib.dom.d.ts(3473,5): error TS2687: All declarations of 'privateKey' must have identical modifiers.
node_modules/typescript/lib/lib.dom.d.ts(3474,5): error TS2687: All declarations of 'publicKey' must have identical modifiers.
node_modules/typescript/lib/lib.webworker.d.ts(25,1): error TS6200: Definitions of the following identifiers conflict with those in another file: EventListenerOrEventListenerObject, BlobPart, HeadersInit, BodyInit, RequestInfo, DOMHighResTimeStamp, CanvasImageSource, MessageEventSource, ImageBitmapSource, TimerHandler, PerformanceEntryList, VibratePattern, AlgorithmIdentifier, HashAlgorithmIdentifier, BigInteger, NamedCurve, GLenum, GLboolean, GLbitfield, GLint, GLsizei, GLintptr, GLsizeiptr, GLuint, GLfloat, GLclampf, TexImageSource, Float32List, Int32List, BufferSource, DOMTimeStamp, FormDataEntryValue, IDBValidKey, Transferable, BinaryType, ClientTypes, EndingType, IDBCursorDirection, IDBRequestReadyState, IDBTransactionMode, KeyFormat, KeyType, KeyUsage, NotificationDirection, NotificationPermission, PushEncryptionKeyName, PushPermissionState, ReferrerPolicy, RequestCache, RequestCredentials, RequestDestination, RequestMode, RequestRedirect, ResponseType, ServiceWorkerState, ServiceWorkerUpdateViaCache, VisibilityState, WebGLPowerPreference, WorkerType, XMLHttpRequestResponseType
node_modules/typescript/lib/lib.webworker.d.ts(85,5): error TS2687: All declarations of 'privateKey' must have identical modifiers.
node_modules/typescript/lib/lib.webworker.d.ts(86,5): error TS2687: All declarations of 'publicKey' must have identical modifiers.
node_modules/typescript/lib/lib.webworker.d.ts(1074,5): error TS2375: Duplicate number index signature.
node_modules/typescript/lib/lib.webworker.d.ts(1360,5): error TS2375: Duplicate number index signature.
node_modules/typescript/lib/lib.webworker.d.ts(1434,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'FormData' must be of type '{ new (form?: HTMLFormElement): FormData; prototype: FormData; }', but here has type '{ new (): FormData; prototype: FormData; }'.
node_modules/typescript/lib/lib.webworker.d.ts(2170,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'Notification' must be of type '{ new (title: string, options?: NotificationOptions): Notification; prototype: Notification; readonly maxActions: number; readonly permission: NotificationPermission; requestPermission(deprecatedCallback?: NotificationPermissionCallback): Promise<...>; }', but here has type '{ new (title: string, options?: NotificationOptions): Notification; prototype: Notification; readonly maxActions: number; readonly permission: NotificationPermission; }'.
node_modules/typescript/lib/lib.webworker.d.ts(4322,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'onmessage' must be of type '(this: Window, ev: MessageEvent) => any', but here has type '(this: DedicatedWorkerGlobalScope, ev: MessageEvent) => any'.
node_modules/typescript/lib/lib.webworker.d.ts(4332,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'location' must be of type 'Location', but here has type 'WorkerLocation'.
node_modules/typescript/lib/lib.webworker.d.ts(4333,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'onerror' must be of type 'OnErrorEventHandlerNonNull', but here has type '(this: DedicatedWorkerGlobalScope, ev: ErrorEvent) => any'.
node_modules/typescript/lib/lib.webworker.d.ts(4335,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'self' must be of type 'Window', but here has type 'WorkerGlobalScope'.
node_modules/typescript/lib/lib.webworker.d.ts(4344,13): error TS2403: Subsequent variable declarations must have the same type.  Variable 'navigator' must be of type 'Navigator', but here has type 'WorkerNavigator'.

Here is my package.json file:

    {
  "name": "app-name",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^8.0.0",
    "@angular/cdk": "^8.0.0",
    "@angular/common": "^8.0.0",
    "@angular/compiler": "^8.0.0",
    "@angular/core": "^8.0.0",
    "@angular/fire": "^5.1.3",
    "@angular/forms": "^8.0.0",
    "@angular/material": "^8.0.0",
    "@angular/platform-browser": "^8.0.0",
    "@angular/platform-browser-dynamic": "^8.0.0",
    "@angular/router": "^8.0.0",
    "bootstrap": "^4.3.1",
    "classlist.js": "^1.1.20150312",
    "core-js": "^2.5.4",
    "firebase": "^5.11.1",
    "hammerjs": "^2.0.8",
    "material-design-icons": "^3.0.1",
    "rxjs": "^6.5.2",
    "save": "^2.3.3",
    "smoothscroll-polyfill": "^0.4.3",
    "tslib": "^1.9.0",
    "web-animations-js": "github:angular/web-animations-js#release_pr208",
    "zone.js": "~0.9.1"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.800.1",
    "@angular/cli": "^8.0.1",
    "@angular/compiler-cli": "^8.0.0",
    "@angular/language-service": "^8.0.0",
    "@types/jasmine": "~3.3.0",
    "@types/jasminewd2": "~2.0.6",
    "@types/node": "~12.0.3",
    "codelyzer": "^5.0.1",
    "jasmine-core": "~3.3.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "^4.0.1",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.4",
    "karma-jasmine": "~2.0.1",
    "karma-jasmine-html-reporter": "^1.4.0",
    "protractor": "~5.4.1",
    "ts-node": "~7.0.1",
    "tslint": "~5.11.0",
    "typescript": "^3.4.5"
  }
}

Thanks.


问:
How to sort an array of a structure using qsort?
A friend and I are trying to teach ourselves C and have decided to do, a what was first thought to be easy, an exercise, where we create a struct of two char containing 1. the forename and 2. the surname. A function read_person gets the users input, saves it in the structure and returns it. The input should be saved in a dynamically allocated array (all of which we have allegedly done correct so far). Then, using qsort, the array should be sorted ascendingly when it comes to the forename, descendingly when it comes to the surname and lastly, considering the length of the forename. if the forenames are equally long, the surnames should be compared. Both of us were trying really hard to make the qsort work but it just wouldn't sort, therefore we were wondering whether anyone has an idea how to do it?</p>

```<code>#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct details{
  char forename[10];
  char surname[10];
}[5];

struct details read_person(){
struct details d;
printf("Enter your forename: ");
fgets(d.forename, 10, stdin);
printf("Enter your surname: ");
fgets(d.surname, 10, stdin);
struct details *arr_dt=malloc(5 * sizeof(struct details));
free(arr_dt);
return d;
}

int main(){
read_person();
return 0;
}
</code>```

答:
You have a number of things going on here that are just not right, but that also touch on a few subtle issues that won't be apparent in attempting to stumble though how to fill your struct.

First, you declare a global array of struct details (5 of them). Don't do that. While legal, instead you simply want to declare the struct at global scope and then declare each instance within main() and pass either a copy of the struct, or a pointer to the struct as parameters to any function within your code that needs it.

Second, you declare d local to read_person and then return d at the end for assignment back in main(). This is fine, ... but ... understand why it is fine. When you declare d all members of struct details all have automatic storage type and storage for each member is fully defined at that point. There is no need to call malloc anywhere in your function. When you return d at the end, struct assignment allows the function to return the struct and have all values assigned and available back in main().

Finally in main(), you call read_person(); but fail to assign the return or make  use of the stored values in d in any way.

Instead of creating a global array of struct, simply declare the struct itself, e.g.:

```<code>#define MAXNM  32   /* if you need a constant, #define one (or more) */
                    /* (don't skimp on buffer size) */
struct details {
    char forename[MAXNM];
    char surname[MAXNM];
};
</code>```

Then for your read_person(void) function, eliminate the calls to malloc and simply do:

```<code>struct details read_person (void)
{
    struct details d;

    printf ("Enter your forename: ");
    fgets (d.forename, MAXNM, stdin);
    d.forename[strcspn(d.forename, "\n")] = 0;  /* trim \n from end */

    printf("Enter your surname : ");
    fgets(d.surname, MAXNM, stdin);
    d.surname[strcspn(d.surname, "\n")] = 0;    /* trim \n from end */

    return d;
}
</code>```

(note: you do not want the line-ending '\n' left at the end of each of the names, so you need to overwrite the trailing '\n' with the nul-character '\0' (or equivalently 0). While there are several ways to do this, the use of strcspn is probably one of the most robust and simplest ways to do this. strcspn returns the number of characters in the string NOT included in the exclude set. So simply have your exclude set include the line-ending "\n" and it returns the number of characters in the string up to the '\n' which you then simply set to 0)

(also note: the use of void in struct details read_person (void) to specify that read_person takes no arguments. In C if you simply leave empty (), then the function takes an indeterminate number of arguments)

Then in main() assign the return and use it in some fashion, e.g.

```<code>int main (void) {

    struct details person = read_person();

    printf ("\nname: %s, %s\n", person.forename, person.surname);

    return 0;
}
</code>```

You other alternative is to declare your struct in main() and pass a pointer to your read_person function for filling. Simply declare a struct in main() and then pass the address of the struct to read_person, but note that with a pointer to struct you use the -> operator to access members rather than '.'. For example you could do:

```<code>#include <stdio.h>
#include <string.h>

#define MAXNM  32   /* if you need a constant, #define one (or more) */
                    /* (don't skimp on buffer size) */
struct details {
    char forename[MAXNM];
    char surname[MAXNM];
};

void read_person (struct details *d)
{
    printf ("Enter your forename: ");
    fgets (d->forename, MAXNM, stdin);
    d->forename[strcspn(d->forename, "\n")] = 0;  /* trim \n from end */

    printf("Enter your surname : ");
    fgets(d->surname, MAXNM, stdin);
    d->surname[strcspn(d->surname, "\n")] = 0;    /* trim \n from end */
}

int main (void) {

    struct details person;

    read_person (&person);

    printf ("\nname: %s, %s\n", person.forename, person.surname);

    return 0;
}
</code>```

And finally, since you did include mailloc, you may as well learn how you could have used it to allocate storage for the struct, as well as each forename and surname so that both use exactly the correct number of bytes to hold the names entered and no more. When allocating storage for anything you have 3 responsibilities regarding any block of memory allocated: (1) always validate the allocations succeeds before making use of the block of memory, (2) always preserve a pointer to the starting address for the block of memory so, (3) it can be freed when it is no longer needed.

That will add a few repetitive, but important, lines of code wherever you dynamically allocate storage. For example in this case where you dynamically allocate for the struct and for forename and surname within the struct, your struct declaration and function, could be:

```<code>struct details {
    char *forename;
    char *surname;
};

struct details *read_person (void)
{
    char buf[MAXNM];
    size_t len;
    struct details *d = malloc (sizeof *d);  /* allocate storage */

    if (d == NULL) {                         /* validate allocation succeeds */
        perror ("malloc-d");
        return NULL;
    }

    printf ("Enter your forename: ");
    fgets (buf, MAXNM, stdin);
    len = strcspn(buf, "\n");
    buf[len] = 0;
    d->forename = malloc (len + 1);      /* allocate */
    if (d->forename == NULL) {           /* validate */
        perror ("malloc-d->forename");
        free (d);
        return NULL;
    }
    memcpy (d->forename, buf, len + 1);

    printf ("Enter your surname : ");
    fgets (buf, MAXNM, stdin);
    len = strcspn(buf, "\n");
    buf[len] = 0;
    d->surname = malloc (len + 1);       /* allocate */
    if (d->surname == NULL) {            /* validate */
        perror ("malloc-d->surname");
        free (d->forename);
        free (d);
        return NULL;
    }
    memcpy (d->surname, buf, len + 1);

    return d;
}
</code>```

(note: the use of memcpy rather than strcpy. You have already scanned for the end-of-string with strcspn to obtain the number of characters in the string and then nul-termianted the string at that point. There is no need to scan for end-of-string again with strcpy, just copy the number of characters (+1 to also copy the nul-terminating character) with memcpy.

Try to see if you can understand why the free() function is include in the function above and what purpose it is serving.

Putting a complete example together that dynamically allocates, you could do something similar to the following:

```<code>#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAXNM  1024

struct details {
    char *forename;
    char *surname;
};

struct details *read_person (void)
{
    char buf[MAXNM];
    size_t len;
    struct details *d = malloc (sizeof *d);

    if (d == NULL) {
        perror ("malloc-d");
        return NULL;
    }

    printf ("Enter your forename: ");
    fgets (buf, MAXNM, stdin);
    len = strcspn(buf, "\n");
    buf[len] = 0;
    d->forename = malloc (len + 1);
    if (d->forename == NULL) {
        perror ("malloc-d->forename");
        free (d);
        return NULL;
    }
    memcpy (d->forename, buf, len + 1);

    printf ("Enter your surname : ");
    fgets (buf, MAXNM, stdin);
    len = strcspn(buf, "\n");
    buf[len] = 0;
    d->surname = malloc (len + 1);
    if (d->surname == NULL) {
        perror ("malloc-d->surname");
        free (d->forename);
        free (d);
        return NULL;
    }
    memcpy (d->surname, buf, len + 1);

    return d;
}

int main (void) {

    struct details *person = read_person();

    if (person != NULL) {   /* validate the function succeeded */
        printf ("\nname: %s, %s\n", person->forename, person->surname);

        free (person->forename);
        free (person->surname);
        free (person);
    }

    return 0;
}
</code>```

(note: all memory is freed before the program exits. Understand that the memory would be freed automatically on exit, but if you make a habit of always taking care of your 3-responsibilities concerning dynamically allocated memory, you will never have problems leaking memory later on as your code size grows.)

Example Use/Output

All of the examples produce the same output. An example would be:

```<code>$ ./bin/struct_name3
Enter your forename: Samuel
Enter your surname : Clemens

name: Samuel, Clemens
</code>```

Memory Use/Error Check

It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.

For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.

```<code>$ valgrind ./bin/struct_name3
==14430== Memcheck, a memory error detector
==14430== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==14430== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==14430== Command: ./bin/struct_name3
==14430==
Enter your forename: Samuel
Enter your surname : Clemens

name: Samuel, Clemens
==14430==
==14430== HEAP SUMMARY:
==14430==     in use at exit: 0 bytes in 0 blocks
==14430==   total heap usage: 3 allocs, 3 frees, 31 bytes allocated
==14430==
==14430== All heap blocks were freed -- no leaks are possible
==14430==
==14430== For counts of detected and suppressed errors, rerun with: -v
==14430== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
</code>```

Always confirm that you have freed all memory you have allocated and that there are no memory errors.

Handling qsort of Array of struct details

After handling all of the initial problems with your use of struct details, I came close to forgetting that your original question related to qsort. qsort is simple to use, you just pass the array, the number of members to sort, the size of each member, and a compare function that returns -1, 0, 1 based on whether the first element sorts before, is equal to, or sorts after the second element passed to the function.

Your only responsibility using qsort is to write the compare function. While new users to qsort usually have their eyes roll back in their heads when they see the declaration for the function:

```<code>int compare (const void *a, const void *b) { ... }
</code>```

It's actually quite simple. a and b are simply pointers to elements of the array to compare. So if you have an array of struct details. The a and b are just pointers to struct details. You simply need to write your compare function to cast a and b to the appropriate type.

To sort on forename, you compare function could be:

```<code>int compare_fore (const void *a, const void *b)
{
    const struct details *name1 = a,
                         *name2 = b;
    int rtn = strcmp (name1->forename, name2->forename); /* compare forename */

    if (rtn != 0)       /* if forenames are different */
        return rtn;     /* return result of strcmp */

    /* otherwise return result of strcmp of surname */
    return strcmp (name1->surname, name2->surname);      /* compare surname */
}
</code>```

To sort on surname, you would have:

```<code>int compare_sur (const void *a, const void *b)
{
    const struct details *name1 = a,
                         *name2 = b;
    int rtn = strcmp (name1->surname, name2->surname);

    if (rtn != 0)
        return rtn;

    return strcmp (name1->forename, name2->forename);
}
</code>```

Then within main() you simply declare an array of struct details and call qsort, e.g.

```<code>int main (void) {

    struct details person[MAXS];

    for (int i = 0; i < MAXS; i++)
        person[i] = read_person();

    qsort (person, MAXS, sizeof *person, compare_fore);

    puts ("\nSorted by forename:\n");
    for (int i = 0; i < MAXS; i++)
        printf ("  %s, %s\n", person[i].forename, person[i].surname);

    qsort (person, MAXS, sizeof *person, compare_sur);

    puts ("\nSorted by surname:\n");
    for (int i = 0; i < MAXS; i++)
        printf ("  %s, %s\n", person[i].forename, person[i].surname);

    return 0;
}
</code>```

Or, putting it altogether in a full example you would have:

```<code>#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXS    5   /* if you need a constant, #define one (or more) */
#define MAXNM  32   /* (don't skimp on buffer size) */

struct details {
    char forename[MAXNM];
    char surname[MAXNM];
};

int compare_fore (const void *a, const void *b)
{
    const struct details *name1 = a,
                         *name2 = b;
    int rtn = strcmp (name1->forename, name2->forename); /* compare forename */

    if (rtn != 0)       /* if forenames are different */
        return rtn;     /* return result of strcmp */

    /* otherwise return result of strcmp of surname */
    return strcmp (name1->surname, name2->surname);      /* compare surname */
}

int compare_sur (const void *a, const void *b)
{
    const struct details *name1 = a,
                         *name2 = b;
    int rtn = strcmp (name1->surname, name2->surname);

    if (rtn != 0)
        return rtn;

    return strcmp (name1->forename, name2->forename);
}

struct details read_person (void)
{
    struct details d;

    printf ("\nEnter your forename: ");
    fgets (d.forename, MAXNM, stdin);
    d.forename[strcspn(d.forename, "\n")] = 0;  /* trim \n from end */

    printf("Enter your surname : ");
    fgets(d.surname, MAXNM, stdin);
    d.surname[strcspn(d.surname, "\n")] = 0;    /* trim \n from end */

    return d;
}

int main (void) {

    struct details person[MAXS];

    for (int i = 0; i < MAXS; i++)
        person[i] = read_person();

    qsort (person, MAXS, sizeof *person, compare_fore);

    puts ("\nSorted by forename:\n");
    for (int i = 0; i < MAXS; i++)
        printf ("  %s, %s\n", person[i].forename, person[i].surname);

    qsort (person, MAXS, sizeof *person, compare_sur);

    puts ("\nSorted by surname:\n");
    for (int i = 0; i < MAXS; i++)
        printf ("  %s, %s\n", person[i].forename, person[i].surname);

    return 0;
}
</code>```

Example Use/Output

```<code>$ ./bin/struct_name4

Enter your forename: Mickey
Enter your surname : Mouse

Enter your forename: Minnie
Enter your surname : Mouse

Enter your forename: Samuel
Enter your surname : Clemens

Enter your forename: Mark
Enter your surname : Twain

Enter your forename: Walt
Enter your surname : Disney

Sorted by forename:

  Mark, Twain
  Mickey, Mouse
  Minnie, Mouse
  Samuel, Clemens
  Walt, Disney

Sorted by surname:

  Samuel, Clemens
  Walt, Disney
  Mickey, Mouse
  Minnie, Mouse
  Mark, Twain
</code>```

(note: since Mickey and Minnie both have last name Mouse, for the sort by surname they are then further sorted by forname so there is a correct cannonical sort in the list above)

Now, hopefully, we have address all the aspects of your question. Look things over and let me know if you have further questions.

Body:
A friend and I are trying to teach ourselves C and have decided to do, a what was first thought to be easy, an exercise, where we create a struct of two char containing 1. the forename and 2. the surname. A function read_person gets the users input, saves it in the structure and returns it. The input should be saved in a dynamically allocated array (all of which we have allegedly done correct so far). Then, using qsort, the array should be sorted ascendingly when it comes to the forename, descendingly when it comes to the surname and lastly, considering the length of the forename. if the forenames are equally long, the surnames should be compared. Both of us were trying really hard to make the qsort work but it just wouldn't sort, therefore we were wondering whether anyone has an idea how to do it?

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct details{
  char forename[10];
  char surname[10];
}[5];

struct details read_person(){
struct details d;
printf("Enter your forename: ");
fgets(d.forename, 10, stdin);
printf("Enter your surname: ");
fgets(d.surname, 10, stdin);
struct details *arr_dt=malloc(5 * sizeof(struct details));
free(arr_dt);
return d;
}

int main(){
read_person();
return 0;
}

Body:
You have a number of things going on here that are just not right, but that also touch on a few subtle issues that won't be apparent in attempting to stumble though how to fill your struct.

First, you declare a global array of struct details (5 of them). Don't do that. While legal, instead you simply want to declare the struct at global scope and then declare each instance within main() and pass either a copy of the struct, or a pointer to the struct as parameters to any function within your code that needs it.

Second, you declare d local to read_person and then return d at the end for assignment back in main(). This is fine, ... but ... understand why it is fine. When you declare d all members of struct details all have automatic storage type and storage for each member is fully defined at that point. There is no need to call malloc anywhere in your function. When you return d at the end, struct assignment allows the function to return the struct and have all values assigned and available back in main().

Finally in main(), you call read_person(); but fail to assign the return or make  use of the stored values in d in any way.

Instead of creating a global array of struct, simply declare the struct itself, e.g.:

#define MAXNM  32   /* if you need a constant, #define one (or more) */
                    /* (don't skimp on buffer size) */
struct details {
    char forename[MAXNM];
    char surname[MAXNM];
};

Then for your read_person(void) function, eliminate the calls to malloc and simply do:

struct details read_person (void)
{
    struct details d;

    printf ("Enter your forename: ");
    fgets (d.forename, MAXNM, stdin);
    d.forename[strcspn(d.forename, "\n")] = 0;  /* trim \n from end */

    printf("Enter your surname : ");
    fgets(d.surname, MAXNM, stdin);
    d.surname[strcspn(d.surname, "\n")] = 0;    /* trim \n from end */

    return d;
}

(note: you do not want the line-ending '\n' left at the end of each of the names, so you need to overwrite the trailing '\n' with the nul-character '\0' (or equivalently 0). While there are several ways to do this, the use of strcspn is probably one of the most robust and simplest ways to do this. strcspn returns the number of characters in the string NOT included in the exclude set. So simply have your exclude set include the line-ending "\n" and it returns the number of characters in the string up to the '\n' which you then simply set to 0)

(also note: the use of void in struct details read_person (void) to specify that read_person takes no arguments. In C if you simply leave empty (), then the function takes an indeterminate number of arguments)

Then in main() assign the return and use it in some fashion, e.g.

int main (void) {

    struct details person = read_person();

    printf ("\nname: %s, %s\n", person.forename, person.surname);

    return 0;
}

You other alternative is to declare your struct in main() and pass a pointer to your read_person function for filling. Simply declare a struct in main() and then pass the address of the struct to read_person, but note that with a pointer to struct you use the -> operator to access members rather than '.'. For example you could do:

#include <stdio.h>
#include <string.h>

#define MAXNM  32   /* if you need a constant, #define one (or more) */
                    /* (don't skimp on buffer size) */
struct details {
    char forename[MAXNM];
    char surname[MAXNM];
};

void read_person (struct details *d)
{
    printf ("Enter your forename: ");
    fgets (d->forename, MAXNM, stdin);
    d->forename[strcspn(d->forename, "\n")] = 0;  /* trim \n from end */

    printf("Enter your surname : ");
    fgets(d->surname, MAXNM, stdin);
    d->surname[strcspn(d->surname, "\n")] = 0;    /* trim \n from end */
}

int main (void) {

    struct details person;

    read_person (&person);

    printf ("\nname: %s, %s\n", person.forename, person.surname);

    return 0;
}

And finally, since you did include mailloc, you may as well learn how you could have used it to allocate storage for the struct, as well as each forename and surname so that both use exactly the correct number of bytes to hold the names entered and no more. When allocating storage for anything you have 3 responsibilities regarding any block of memory allocated: (1) always validate the allocations succeeds before making use of the block of memory, (2) always preserve a pointer to the starting address for the block of memory so, (3) it can be freed when it is no longer needed.

That will add a few repetitive, but important, lines of code wherever you dynamically allocate storage. For example in this case where you dynamically allocate for the struct and for forename and surname within the struct, your struct declaration and function, could be:

struct details {
    char *forename;
    char *surname;
};

struct details *read_person (void)
{
    char buf[MAXNM];
    size_t len;
    struct details *d = malloc (sizeof *d);  /* allocate storage */

    if (d == NULL) {                         /* validate allocation succeeds */
        perror ("malloc-d");
        return NULL;
    }

    printf ("Enter your forename: ");
    fgets (buf, MAXNM, stdin);
    len = strcspn(buf, "\n");
    buf[len] = 0;
    d->forename = malloc (len + 1);      /* allocate */
    if (d->forename == NULL) {           /* validate */
        perror ("malloc-d->forename");
        free (d);
        return NULL;
    }
    memcpy (d->forename, buf, len + 1);

    printf ("Enter your surname : ");
    fgets (buf, MAXNM, stdin);
    len = strcspn(buf, "\n");
    buf[len] = 0;
    d->surname = malloc (len + 1);       /* allocate */
    if (d->surname == NULL) {            /* validate */
        perror ("malloc-d->surname");
        free (d->forename);
        free (d);
        return NULL;
    }
    memcpy (d->surname, buf, len + 1);

    return d;
}

(note: the use of memcpy rather than strcpy. You have already scanned for the end-of-string with strcspn to obtain the number of characters in the string and then nul-termianted the string at that point. There is no need to scan for end-of-string again with strcpy, just copy the number of characters (+1 to also copy the nul-terminating character) with memcpy.

Try to see if you can understand why the free() function is include in the function above and what purpose it is serving.

Putting a complete example together that dynamically allocates, you could do something similar to the following:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAXNM  1024

struct details {
    char *forename;
    char *surname;
};

struct details *read_person (void)
{
    char buf[MAXNM];
    size_t len;
    struct details *d = malloc (sizeof *d);

    if (d == NULL) {
        perror ("malloc-d");
        return NULL;
    }

    printf ("Enter your forename: ");
    fgets (buf, MAXNM, stdin);
    len = strcspn(buf, "\n");
    buf[len] = 0;
    d->forename = malloc (len + 1);
    if (d->forename == NULL) {
        perror ("malloc-d->forename");
        free (d);
        return NULL;
    }
    memcpy (d->forename, buf, len + 1);

    printf ("Enter your surname : ");
    fgets (buf, MAXNM, stdin);
    len = strcspn(buf, "\n");
    buf[len] = 0;
    d->surname = malloc (len + 1);
    if (d->surname == NULL) {
        perror ("malloc-d->surname");
        free (d->forename);
        free (d);
        return NULL;
    }
    memcpy (d->surname, buf, len + 1);

    return d;
}

int main (void) {

    struct details *person = read_person();

    if (person != NULL) {   /* validate the function succeeded */
        printf ("\nname: %s, %s\n", person->forename, person->surname);

        free (person->forename);
        free (person->surname);
        free (person);
    }

    return 0;
}

(note: all memory is freed before the program exits. Understand that the memory would be freed automatically on exit, but if you make a habit of always taking care of your 3-responsibilities concerning dynamically allocated memory, you will never have problems leaking memory later on as your code size grows.)

Example Use/Output

All of the examples produce the same output. An example would be:

$ ./bin/struct_name3
Enter your forename: Samuel
Enter your surname : Clemens

name: Samuel, Clemens

Memory Use/Error Check

It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.

For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.

$ valgrind ./bin/struct_name3
==14430== Memcheck, a memory error detector
==14430== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==14430== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==14430== Command: ./bin/struct_name3
==14430==
Enter your forename: Samuel
Enter your surname : Clemens

name: Samuel, Clemens
==14430==
==14430== HEAP SUMMARY:
==14430==     in use at exit: 0 bytes in 0 blocks
==14430==   total heap usage: 3 allocs, 3 frees, 31 bytes allocated
==14430==
==14430== All heap blocks were freed -- no leaks are possible
==14430==
==14430== For counts of detected and suppressed errors, rerun with: -v
==14430== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Always confirm that you have freed all memory you have allocated and that there are no memory errors.

Handling qsort of Array of struct details

After handling all of the initial problems with your use of struct details, I came close to forgetting that your original question related to qsort. qsort is simple to use, you just pass the array, the number of members to sort, the size of each member, and a compare function that returns -1, 0, 1 based on whether the first element sorts before, is equal to, or sorts after the second element passed to the function.

Your only responsibility using qsort is to write the compare function. While new users to qsort usually have their eyes roll back in their heads when they see the declaration for the function:

int compare (const void *a, const void *b) { ... }

It's actually quite simple. a and b are simply pointers to elements of the array to compare. So if you have an array of struct details. The a and b are just pointers to struct details. You simply need to write your compare function to cast a and b to the appropriate type.

To sort on forename, you compare function could be:

int compare_fore (const void *a, const void *b)
{
    const struct details *name1 = a,
                         *name2 = b;
    int rtn = strcmp (name1->forename, name2->forename); /* compare forename */

    if (rtn != 0)       /* if forenames are different */
        return rtn;     /* return result of strcmp */

    /* otherwise return result of strcmp of surname */
    return strcmp (name1->surname, name2->surname);      /* compare surname */
}

To sort on surname, you would have:

int compare_sur (const void *a, const void *b)
{
    const struct details *name1 = a,
                         *name2 = b;
    int rtn = strcmp (name1->surname, name2->surname);

    if (rtn != 0)
        return rtn;

    return strcmp (name1->forename, name2->forename);
}

Then within main() you simply declare an array of struct details and call qsort, e.g.

int main (void) {

    struct details person[MAXS];

    for (int i = 0; i < MAXS; i++)
        person[i] = read_person();

    qsort (person, MAXS, sizeof *person, compare_fore);

    puts ("\nSorted by forename:\n");
    for (int i = 0; i < MAXS; i++)
        printf ("  %s, %s\n", person[i].forename, person[i].surname);

    qsort (person, MAXS, sizeof *person, compare_sur);

    puts ("\nSorted by surname:\n");
    for (int i = 0; i < MAXS; i++)
        printf ("  %s, %s\n", person[i].forename, person[i].surname);

    return 0;
}

Or, putting it altogether in a full example you would have:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXS    5   /* if you need a constant, #define one (or more) */
#define MAXNM  32   /* (don't skimp on buffer size) */

struct details {
    char forename[MAXNM];
    char surname[MAXNM];
};

int compare_fore (const void *a, const void *b)
{
    const struct details *name1 = a,
                         *name2 = b;
    int rtn = strcmp (name1->forename, name2->forename); /* compare forename */

    if (rtn != 0)       /* if forenames are different */
        return rtn;     /* return result of strcmp */

    /* otherwise return result of strcmp of surname */
    return strcmp (name1->surname, name2->surname);      /* compare surname */
}

int compare_sur (const void *a, const void *b)
{
    const struct details *name1 = a,
                         *name2 = b;
    int rtn = strcmp (name1->surname, name2->surname);

    if (rtn != 0)
        return rtn;

    return strcmp (name1->forename, name2->forename);
}

struct details read_person (void)
{
    struct details d;

    printf ("\nEnter your forename: ");
    fgets (d.forename, MAXNM, stdin);
    d.forename[strcspn(d.forename, "\n")] = 0;  /* trim \n from end */

    printf("Enter your surname : ");
    fgets(d.surname, MAXNM, stdin);
    d.surname[strcspn(d.surname, "\n")] = 0;    /* trim \n from end */

    return d;
}

int main (void) {

    struct details person[MAXS];

    for (int i = 0; i < MAXS; i++)
        person[i] = read_person();

    qsort (person, MAXS, sizeof *person, compare_fore);

    puts ("\nSorted by forename:\n");
    for (int i = 0; i < MAXS; i++)
        printf ("  %s, %s\n", person[i].forename, person[i].surname);

    qsort (person, MAXS, sizeof *person, compare_sur);

    puts ("\nSorted by surname:\n");
    for (int i = 0; i < MAXS; i++)
        printf ("  %s, %s\n", person[i].forename, person[i].surname);

    return 0;
}

Example Use/Output

$ ./bin/struct_name4

Enter your forename: Mickey
Enter your surname : Mouse

Enter your forename: Minnie
Enter your surname : Mouse

Enter your forename: Samuel
Enter your surname : Clemens

Enter your forename: Mark
Enter your surname : Twain

Enter your forename: Walt
Enter your surname : Disney

Sorted by forename:

  Mark, Twain
  Mickey, Mouse
  Minnie, Mouse
  Samuel, Clemens
  Walt, Disney

Sorted by surname:

  Samuel, Clemens
  Walt, Disney
  Mickey, Mouse
  Minnie, Mouse
  Mark, Twain

(note: since Mickey and Minnie both have last name Mouse, for the sort by surname they are then further sorted by forname so there is a correct cannonical sort in the list above)

Now, hopefully, we have address all the aspects of your question. Look things over and let me know if you have further questions.


问:
How to run a BigQuery query in Python
This is the query that I have been running in BigQuery that I want to run in my python script. How would I change this/ what do I have to add for it to run in Python.

```<code>#standardSQL
SELECT
  Serial,
  MAX(createdAt) AS Latest_Use,
  SUM(ConnectionTime/3600) as Total_Hours,
  COUNT(DISTINCT DeviceID) AS Devices_Connected
FROM `dataworks-356fa.FirebaseArchive.testf`
WHERE Model = "BlueBox-pH"
GROUP BY Serial
ORDER BY Serial
LIMIT 1000;
</code>```

From what I have been researching it is saying that I cant save this query as a permanent table using Python. Is that true? and if it is true is it possible to still export a temporary table?

答:
This is a good usage guide:
https://googleapis.github.io/google-cloud-python/latest/bigquery/usage/index.html

To simply run and write a query:

```<code># from google.cloud import bigquery
# client = bigquery.Client()
# dataset_id = 'your_dataset_id'

job_config = bigquery.QueryJobConfig()
# Set the destination table
table_ref = client.dataset(dataset_id).table("your_table_id")
job_config.destination = table_ref
sql = """
    SELECT corpus
    FROM `bigquery-public-data.samples.shakespeare`
    GROUP BY corpus;
"""

# Start the query, passing in the extra configuration.
query_job = client.query(
    sql,
    # Location must match that of the dataset(s) referenced in the query
    # and of the destination table.
    location="US",
    job_config=job_config,
)  # API request - starts the query

query_job.result()  # Waits for the query to finish
print("Query results loaded to table {}".format(table_ref.path))
</code>```

Title: How to run a BigQuery query in Python

Body:
This is the query that I have been running in BigQuery that I want to run in my python script. How would I change this/ what do I have to add for it to run in Python.

#standardSQL
SELECT
  Serial,
  MAX(createdAt) AS Latest_Use,
  SUM(ConnectionTime/3600) as Total_Hours,
  COUNT(DISTINCT DeviceID) AS Devices_Connected
FROM `dataworks-356fa.FirebaseArchive.testf`
WHERE Model = "BlueBox-pH"
GROUP BY Serial
ORDER BY Serial
LIMIT 1000;

From what I have been researching it is saying that I cant save this query as a permanent table using Python. Is that true? and if it is true is it possible to still export a temporary table?

Body:
This is a good usage guide:
https://googleapis.github.io/google-cloud-python/latest/bigquery/usage/index.html

To simply run and write a query:

# from google.cloud import bigquery
# client = bigquery.Client()
# dataset_id = 'your_dataset_id'

job_config = bigquery.QueryJobConfig()
# Set the destination table
table_ref = client.dataset(dataset_id).table("your_table_id")
job_config.destination = table_ref
sql = """
    SELECT corpus
    FROM `bigquery-public-data.samples.shakespeare`
    GROUP BY corpus;
"""

# Start the query, passing in the extra configuration.
query_job = client.query(
    sql,
    # Location must match that of the dataset(s) referenced in the query
    # and of the destination table.
    location="US",
    job_config=job_config,
)  # API request - starts the query

query_job.result()  # Waits for the query to finish
print("Query results loaded to table {}".format(table_ref.path))


问:
Why does my service principal not have access to my key vault?
We have an existing key vault say kv1 and an existing ad security group say adg1.

adg1 already has an access policy set up that provides get and list access to members of the group.

Using an azure devops pipeline and an arm template we are deploying several resources including a vm scale set say vmss1

At the end, we call an azure automation job that has ad admin access to add vmss1 to adg1

vmss1 is not able to access the secrets in kv1.

If we instead add vmss1 service principal directly to the adg1, it will gain access, if we remove the direct addition, it loses access.

Our AD structure is not very complicated and we waited 2-3 hours for propagation and still nothing.

Here is the powershell that handles the adding:

```<code>$vmssid = (Get-AzureRMADServicePrincipal -DisplayName "$_scaleSetName").Id

if(!$vmssid){
    Write-Error 'Scale set did not exiset or was not a scale set'
    return 1
}

$groupId = (Get-AzureRMAdGroup -AzureRmContext $AzureContext -DisplayName "$webAppGroupName" ).Id
if(!$groupId){
    Write-Error 'Group not found'
    return 1
}

$shouldAddMember = !(Get-AzureRMAdGroupMember -AzureRmContext $AzureContext -GroupObjectId $groupId | ?{$_.Id-eq $vmssid})
if($shouldAddMember ){
 Add-AzureRmAdGroupMember -AzureRmContext $AzureContext -MemberObjectId $vmssId -TargetGroupObjectId $groupId
}
else{
Write-Output 'Member existed in group'
exit 0
}
</code>```

The first run it results in the user getting added, subsequent runs print "Member existed"

答:
It appears that the propagation time of azure AD can be extreme.
After a day or it started working with just the AD group being assigned to the access policy. So I guess the answer is an excruciating amount of patience.</p>

Body:
We have an existing key vault say kv1 and an existing ad security group say adg1.

adg1 already has an access policy set up that provides get and list access to members of the group.

Using an azure devops pipeline and an arm template we are deploying several resources including a vm scale set say vmss1

At the end, we call an azure automation job that has ad admin access to add vmss1 to adg1

vmss1 is not able to access the secrets in kv1.

If we instead add vmss1 service principal directly to the adg1, it will gain access, if we remove the direct addition, it loses access.

Our AD structure is not very complicated and we waited 2-3 hours for propagation and still nothing.

Here is the powershell that handles the adding:

$vmssid = (Get-AzureRMADServicePrincipal -DisplayName "$_scaleSetName").Id

if(!$vmssid){
    Write-Error 'Scale set did not exiset or was not a scale set'
    return 1
}

$groupId = (Get-AzureRMAdGroup -AzureRmContext $AzureContext -DisplayName "$webAppGroupName" ).Id
if(!$groupId){
    Write-Error 'Group not found'
    return 1
}

$shouldAddMember = !(Get-AzureRMAdGroupMember -AzureRmContext $AzureContext -GroupObjectId $groupId | ?{$_.Id-eq $vmssid})
if($shouldAddMember ){
 Add-AzureRmAdGroupMember -AzureRmContext $AzureContext -MemberObjectId $vmssId -TargetGroupObjectId $groupId
}
else{
Write-Output 'Member existed in group'
exit 0
}

The first run it results in the user getting added, subsequent runs print "Member existed"